I am planning to use cryptosupport API to encryp/decrypt certain cookie keys bearing PCI/PII customer data. I am setting/reading these cookies at both client and server side. At server end (java), I am able to call API and encrypt/decrypt. How do I call the API from clientside (javascript) ? The usage is quite huge at clientside and I dont want to make ajax calls to server.
Is it advisable to use this API with requirement of encrypting cookie data used at both client and server side?
Or is there simpler encryption API for this purpose?
It is a server-side AEM capability only.
And think about it--if you were able to call an API to decrypt a cipher on the client side (JavaScript), what security would it provide? End users could easily also decrypt the cipher and see the secret, so it really would defeat the purpose of having an encrypted secret.
See What encryption algorithm is best for encrypting cookies? which says
Since this question is rather popular, I thought it useful to give
it an update.
Let me emphasise the correct answer as given by AviD to this question:
You should not store any data that needs encrypting in your cookie. Instead, store a good sized (128 bits/16 bytes) random key in
the cookie and store the information you want to keep secure on the
server, identified by the cookie's key.
Related
I wanted to use encrypted local PASETO tokens for the Request Object in the OIDC, but it turns out that I need to store the key somewhere to decrypt this request object, and it must be available unencrypted/unhashed as it will need the Request Object to decrypt. So I will have to store it as plain text in a database? Pretty dangerous. So I started to wonder how JWE works, but the documentation from https://datatracker.ietf.org/doc/html/rfc7516#section-5.1 about JWE encryption is quite confusing for me. Does JWE solve this problem of storing a symmetric key in a database as plain text or does it have other ways?
There are a few different solutions here, which solve different problems:
ENCRYPTED JWTs
These can be used when the app wants to prevent information disclosure. They are issued by the Authorization Server, which uses a public key to encrypt them. There is then a burden on the app to maintain a private key to decrypt them. See the Encrypted ID Tokens for some example usage.
REQUEST OBJECTS
These are often used to protect against man in the browser tampering. The app only needs to deal with public keys, which it already has access to, so the solution is easier to manage. Newer standards such as PAR and JARM are used, as in this summary.
JWT INFORMATION DISCLOSURE
If you want to avoid revealing sensitive data in access token JWTs, then the usual technique is to return only opaque access tokens to internet clients. This is easier to manage than encryption. See the Phantom Token Pattern for how this works.
SUMMARY
I would usually avoid introducing key management into apps. Aim to manage this in the Authorization Server instead.
I would like to secure a .NET Web API service. I will be using SSL, but I also need to restrict the Web API calls that each user can call depending on the user's permissions.
From what I've read, REST/HTTP is supposed to be stateless, so technically you shouldn't be able to maintain any session state, but there are some ways around that.
One is to use basic authentication. The credentials are sent with every request. While this may be okay security-wise because they're being transmitted over SSL anyway, it really isn't practical given that it would require a lot of overhead to re-authenticate against the database every time. (A possibility might be to cache them in memory, but I doubt that's the best way.)
Another could be to use an HMAC (example implementation) to control access to API calls. There is a comment in this article that says:
Just to be clear to people that are implementing this on their HTTPS services: YOU DON'T NEED TO IMPLEMENT HMAC ON SSL!!! It's a waste of time and waste of complexity for absolutely no reason. DON'T DO IT. Use Basic Auth and be done with it.
I don't agree with this for the reasons mentioned above (it is more practical to authenticate once and control using HMAC than authenticate every time).
Is it a good and effective practice to use an HMAC to provide security to Web API calls when working over SSL, or are there any points that I am missing?
The answer depends on how much you care about security.
What is this API being used for? If security is a big concern, Basic Authentication is NOT a sufficiently good choice -- even if you're using SSL.
Even if you're using SSL, an attacker who can control or get access to your initial request can pretend to be the desired HTTPS web service, and intercept your traffic easily (then get a hold of your API credentials).
A much better solution is to do several things:
Use an API key and secret.
Generate a unique ID with each request.
Generate a timestamp with each request.
Encrypt the body of your request against your API key secret.
Put the encrypted output into the HTTP_AUTHORIZATION header in the form: API_KEY_ID:<encrypted_output>
On the server side, decrypt the payload.
Compare the timestamp -- if the request was sent more than a second before -- drop it (this prevents timing attacks).
Compare the unique id -- if this request was already executed -- drop it (this prevents replay attacks).
The above strategies make it impossible for attackers to gain access to your API credentials, even if they are able to successfully man-in-the-middle your API calls.
I recently stumbled across this article on securing Web API endpoints.
If I'm using SSL, is there any advantage to encrypting the user string in the header? What are the risks if I include the user key (Id) as plaintext instead of ciphertext?
TLS is transport-level security. I.e. the data is not secured by TLS before the data reaches the transport and after that. If your data is long-term and/or you keep them elsewhere besides using during the transport session, then it might make some sense to keep them encrypted (and then transfer them encrypted if possible). If your data lifetime is short and the data makes sense only during the transport session, then there's no much sense in encrypting the data besides TLS.
The author of the article is basically combining the concepts of a user identifier and a user secret into a single cryptographic token. If you choose to send a user identifier in plaintext instead, then that user identifier must be kept secret (just as the token must be kept secret). As long as that secrecy is maintained there is no advantage to using the token.
Note that this system doesn't seem very secure as presented. If an attacker can guess a valid user identifier then they can generate a valid token. The author is basically using RSA as a glorified hash function. I'd recommend you look for another reference.
How to Encrypt Client side login before sending to server ?
You should use HTTPS.
Building security by yourself is hard, and you are very likely to get it wrong.
You should stick with the systems that the experts use.
On the server, remember to hash and salt the passwords, preferably using bcrypt.
There's one very simple solution. SSL. Ensure that all your login activities are served via https:// URLs.
The way that you do this, at least the "setting the server up" part vary depending on what web server you're using. You'd be better off asking a question of that nature on http://www.serverfault.com/
You can only use https - any client side encryption would be viewable on the client and therefore useless. There is SO question on this: password encryption at client side
You should really use HTTPS, but if you can't use HTTPS then the alternative is to create a hash.
Server generates a random 'salt' for the session
JavaScript on client-side creates a cryptographically secure hash of the user's password and the salt.
Hash is sent to the server, you can then retrieve the password from the database, create a hash using the salt for the session and the password from the DB and check if it is the same as the one sent from the client. - If it is then the password is a match.
An example of using JavaScript to protect passwords: http://pajhome.org.uk/crypt/md5/auth.html
I often make small websites and use the built in ASP.NET membership functionality in a SQL Server database, using the default "hashing" password storage method.
I'm wondering if there's a way to authenticate a user by hashing his password on the client and not sending it in clear text over the wire without using SSL.
I realize that this would only be applicable for users with Javascript enabled.
Or... possibly, this would be a great built-in capability for Silverlight (is this in the Silverlight roadmap?)
EDIT:
I'm also looking for "degrees of security." Meaning, if there is a method that has some advantages over simply sending plaintext password, I'd like to know what they are and why.
I know there are lots of people who do small sites with logins (such as a family website or volunteering to make a site for a local cooking club) and don't see the need for purchasing SSL certificates.
This is possible. This is actually what Kerberos authentication does, only with a little bit of added spice. To ensure that your authentication mechanism is secure, you need the following:
A common hashing algorithm on both the client and server.
A one-time salt value generated on the server and shared with the client.
The original password stored in a database.
To securely authenticate a user via hash code, so you avoid sending the actual password across the wire, first generate a random, single-use salt value on the server. Send this salt value to the client, and generate a hash code from the salted version of the password the user has input. Send the resulting hash code to the server, and compare it with a hash code generated from the salted version of the stored password. If the comparison fails, discard the salt, regenerate a new salt value, and repeat the process.
The reason for the single-use salt is to prevent anyone listening to the conversation from capturing the hash code of the users password, which, when you use hash code comparison, is just as good as having the password itself.
Note that you need to keep the original password around, you can't hash it once on the server and save the hash in the database. If you need to ensure that the passwords stored in your database are also secure, then you will need to encrypt them before storing them. I believe that ASP.NET membership providers do allow you to store passwords encrypted, however, if you really wish to have a secure authentication mechanism that is difficult for a hacker to crack, then I would recommend handling password storage and retrieval entirely on your own.
Finally, I should note, that such a complex password transfer mechanism should be largely unnecessary if you use SSL to encrypt your connection during authentication.
References (for those who have never heard of Kerberos or SRP):
http://en.wikipedia.org/wiki/Kerberos_(protocol)
http://en.wikipedia.org/wiki/Secure_remote_password_protocol
This is a bad idea, security wise. If you send a non-ssl form that contains the hashed password, then anyone capturing traffic has all they need to login. Your javascript has to result in something that indicates success (a redirect, token passed to the server, etc). Whatever it is, the listener now can recreate that without proper authentication.
SSL was built for a reason, by people who tried a lot of other web authentication schemes. It is far safer and cheaper to get a cert than to try write your own safe authentication scheme that works without encryption.
Added for clarity:
Client side hashing alone is not safe. Say I have a form with the following inputs
<form action="signin.whatever" method="post">
<input type="text" id="txtUser">
<input type="text" id="txtPass">
<input type="hidden" id="hiddenHash">
<input type="submit" onclick="hashAndSubmit()">
</form>
where hashAndSubmit() hashes the password and puts it in hiddenHash, and blanks out the password field. If I sniff your submission and see the following fields:
txtUser:joeuser
txtPass:
hiddenHash:xxx345yz // hash result
that's all I need as an attacker. I build a form with your user and hash value and I'm all set. The password is not necessary for a replay attack.
To get around this, you have to look at one-time salt values, or other schemes. All of which introduce more cost(don't forget developer time) and risk than SSL. Before you do something like this, ask one question...
Do I trust myself more than years and years of public testing of the SSL encryption?
You could do this, but it would be just as insecure. The problem is that someone could capture the hash and replay it (just as they could the original password). I suppose you're providing some protection against the exposure of the actual password (in case they use it on other systems), but your system will be no more secure.
You can implement your hashing algorithm client side (in javascript) and send only the user name and hash result over the wire. Note that in order for this to be secure the hash must be salted with a string provided by the server, and the string must be unique for every request. The sever still needs to check whether the hash is correct or not and authenticate the session.
At least you have to use a salt for generating the hash. Otherwise the hash value is as "valuable" as the plain password when intercepted - at least on your site.
You can send as post fields the username/realm/password hash following the HTTP Digest protocol. AFAIK there is no built-in client component nor server side component to generate/validate this so you have to do everything manually. It also requires your storage to store a specific hash format, see Storing password in tables and Digest authentication
The advantage is that you're following a well analyzed and understood authentication protocol. Don't roll your own.