views:

4416

answers:

9

I'm looking for information about 'the best' encryption algorithm for encrypting cookies.

I hava the following requirements:

  • It must be fast
    encrypting and decrypting the data will be done for (nearly) every request

  • It will operate on small data sets, typically strings of around 100 character or less

  • It must be secure, but it's not like we're securing banking transactions

  • We need to be able to decrypt the information so SHA1 and the like are out.

Now I've read that Blowfish is fast and secure, and I've read that AES is fast and secure. With Blowfish having a smaller block size.

I think that both algorithms provide more than adequate security? so the speed would then become the decisive factor. But I really have no idea if those algorithm are suited for small character string and if there are maybe better suited algorithm for encrypting cookies.

So my question is:
What encryption algorithm is best for encrypting cookie data?

Update
To be more precise, we want to encrypt 2 cookie: one with session information and the other with 'remeber me' information.

The platform is PHP as apache module on Linux on a VPS.

Update 2
I agree with cletus that storing any information in a cookie is insecure.

However, we have a requirement to implement a 'remeber me' feature. The accepted way to go about this is by setting a cookie. If the client presents this cookie, he or she is allowed access the system with (almost) equal rights as if he/she presented the valid username password combination.

So we at least want to encrypt all data in the cookie so that it:
a) malicious users can't read it's contents,
b) malicious users can't fabricate their own cookie or tamper with it.

(All data from cookies is sanitized and checked for validity before we do anything with it, but that's another story)

The session cookie contains a sessionId/timestamp nothing more. It could probably be used without encryption, but I see no harm in encrypting it? (other than computation time).

So given that we have to store some data on in a cookie, what is the best way to encrypt it?

Update 3
The responses to this question made me reconsider the chosen approach. I can indeed do the same without the need for encryption. Instead of encrypting the data, I should only send out data that is meaningless without it's context and cannot be guessed.

However, I'm also at a loss:
I thought that encryption enabled us send data out in to the BigBadWorld(tm), and still be (fairly) sure that nobody could read or tamper with the it...
Wasn't that the whole point of encryption?

But the reactions below push toward: Do not trust encryption to accomplish security.

What am I missing??

+9  A: 

This is touching on two separate issues.

Firstly, session hijacking. This is where a third party discovers, say, an authenticated cookie and gains access to someone else's details.

Secondly, there is session data security. By this I mean that you store data in the cookie (such as the username). This is not a good idea. Any such data is fundamentally untrustworthy just like HTML form data is untrustworthy (irrespective of what Javascript validation and/or HTML length restrictions you use, if any) because a client is free to submit what they want.

You'll often find people (rightly) advocating sanitizing HTML form data but cookie data will be blindly accepted on face value. Big mistake. In fact, I never store any information in the cookie. I view it as a session key and that's all.

If you intend to store data in a cookie I strongly advise you to reconsider.

Encryption of this data does not make the information any more trustworth because symmetric encryption is susceptible to brute-force attack. Obviously AES-256 is better than, say, DES (heh) but 256-bits of security doesn't necessarily mean as much as you think it does.

For one thing, SALTs are typically generated according to an algorithm or are otherwise susceptible to attack.

For another, cookie data is a prime candidate for crib attacks. If it is known or suspected that a username is in the encrypted data will hey, there's your crib.

This brings us back to the first point: hijacking.

It should be pointed out that on shared-hosting environments in PHP (as one example) your session data is simply stored on the filesystem and is readable by anyone else on that same host although they don't necessarily know which site it is for. So never store plaintext passwords, credit card numbers, extensive personal details or anything that might otherwise be deemed as sensitive in session data in such environments without some form of encryption or, better yet, just storing a key in the session and storing the actual sensitive data in a database.

Note: the above is not unique to PHP.

But that's server side encryption.

Now you could argue that encrypting a session with some extra data will make it more secure from hijacking. A common example is the user's IP address. Problem is many people use the same PC/laptop at many different locations (eg Wifi hotspots, work, home). Also many environments will use a variety of IP addresses as the source address, particularly in corporate environments.

You might also use the user agent but that's guessable.

So really, as far as I can tell, there's no real reason to use cookie encryption at all. I never did think there was but in light of this question I went looking to be proven either right or wrong. I found a few threads about people suggesting ways to encrypt cookie data, transparently do it with Apache modules, and so on but these all seemed motivated by protecting data stored in a cookie (which imho you shouldn't do).

I've yet to see a security argument for encrypting a cookie that represents nothing more than a session key.

I will happily be proven wrong if someone can point out something to the contrary.

cletus
see update; 1 cookie with session information and 1 'remember me' cookie
Jacco
256 bits provides a LOT of protection, plenty for most uses, more than enough for this situation. That's assuming, of course, that we're talking about 256 bits of RANDOM data... nobody's gonna be cracking that any century soon.
AviD
Secondly, neither salts (which ARE supposed to be random) nor "crib" (aka known plaintext) attacks are (currently) relevant to AES. Overall, there is NO reason to assume or consider that your AES-encrypted data will be decrypted, unless this is an implementation problem (which IS likely ;-) )
AviD
That all said (and I really think 300 chars is too short for comments ;-) ), I agree with the point that it shouldnt need to be encrypted in the first place.
AviD
+6  A: 

No real reason not to go with AES with 256 bits. Make sure to use this in CBC mode, and PKCS#7 padding. As you said, fast and secure.

I have read (not tested) that Blowfish may be marginally faster... However Blowfish has a major drawback of long setup time, which would make it bad for your situation. Also, AES is more "proven".

This assumes that it really is necessary to symmetrically encrypt your cookie data. As others have noted, it really shouldnt be necessary, and there are only a few edge cases where there's no other choice but to do so. Commonly, it would better suit you to change the design, and go back to either random session identifiers, or if necessary one-way hashes (using SHA-256).
In your case, besides the "regular" random session identifier, your issue is the "remember me" feature - this should also be implemented as either:

  • a long random number, stored in the database and mapped to a user account;
  • or a keyed hash (e.g. HMAC) containing e.g. the username, timestamp, mebbe a salt, AND a secret server key. This can of course all be verified server-side...

Seems like we've gotten a little of topic of your original, specific question - and changed the basis of your question by changing the design....
So as long as we're doing that, I would also STRONGLY recommend AGAINST this feature of persistent "remember me", for several reasons, the biggest among them:

  • Makes it much more likely that someone may steal that user's remember key, allowing them to spoof the user's identity (and then probably change his password);
  • CSRF - Cross Site Request Forgery. Your feature will effectively allow an anonymous attacker to cause unknowing users to submit "authenticated" requests to your application, even without being actually logged in.
AviD
I'm aware of the dangers of the remember me feature, account damaging actions or password changes are not allowed without entering the password. also there is (some) CSRF protection as well, but other people using the same computer for example can login. We try to warn/educate our user about that.
Jacco
In the end, no-one cares about privacy or security. That is why every large site from gmail to amazon has a "remember me" checkbox. People would rather lose data or be hacked than enter their passwords. So, give them what they want because all the people you are competing with already do.
Xeoncross
+2  A: 

While both a very strong ones, AES is a standard.

As for security of small chunks of data: the smaller - the better. The less encrypted data is exposed, the longer you can use the key. There is always a theoretical limit of how much data can be encrypted within one key of given algorithm without exposing system to risks.

inazaruk
A: 

AES (also known as Rijndael) is the most popular. The block size is 128-bits, that's only 16-bytes, and you're talking "around 100 characters".

vartec
+1  A: 

Why do you want to encrypt the cookie?

As I see it, there are two cases: either you give the client the key, or you don't.

If you don't give the key to the client, then why are you giving them the data? Unless you're playing some weird game with breaking weak encryption (which you're explicitly not), you might as well store the data on the server.

If you do hand the client the key, then why do you encrypt it in the first place? If you don't encrypt the communication of the key, then encrypting the cookie is moot: a MITM can look at the cookie and send you any cookie he wants. If you use an encrypted channel to the client, why the extra overhead of encrypting the stored data?

If you're worried about other users on the client's machine reading the cookie, give up and assume the browser sets good permission bits :)

Jonas Kölker
"give up and assume the browser sets good permission bits" I've given up on making any assumptions about correct browser behaviour.
Jacco
point taken :DWhat I think I meant was: that's not your responsibility. Defer it to those whom it belongs to. It feels like taking on that responsibility would be adding crap to work around other crap. I'd rather see a world with less crap :D*sigh*... I hate software right now ;)
Jonas Kölker
+1  A: 

You can achieve what you want securely by using AES in EAX mode. The ciphertext will be larger than the plaintext; that's normal for secure encryption.

The attacker will of course know the length of your plaintext from the ciphertext, but they shouldn't be able to determine anything else.

Generate AES keys randomly.

Be sure and use a fresh nonce for each encryption, and use the "associated data" field to ensure that a thing you encrypted for one purpose isn't presented as being for another (so things like the user name and cookie name could go in there)

the reactions below push toward: Do not trust encryption to accomplish security.

More "if you're not an encryption expert you'll underestimate how easy it is to get wrong". For example, AFAICT no-one else in this thread has discussed chaining modes or message integrity, which covers two common beginner's mistakes.

Paul Crowley
A: 

If you encrypt the cookie, the server still has to decode it to read it (to check for same key), therefore any encrypted cookie is pointless, because if stolen (and un-edited) it will still lead the hacker right to your account. Its just as unsafe as no encrypted at all.

I believe the real issue of someone stealing your cookie is the connection between the server and client. Use SSL connection provided by your host.

As for your cookie, you need to make a long random id per user in the database, (have it change every log on) and just set that as the cookie or session. The cookie that contains the key can be checked via php and if it is equal to an account or table in your database, dump the data on the web page like normal.

mike
Yes, but the contents of that cookie is still secure.
Jacco
A: 

I think that "giving away" any data even encrypted when it is about username and password is not good ... There are many JS that can sniff it ... I suggest you create in users DB table a field cookie_auth or whatever ...

after first login gather : current: browser, IP,ans some own salt key, plus your hostname var ...

create a hash and store in that field ... set a cookie ... when cookie "responds" compare all of these with the stored hash and done ...

even if someone "steal" a cookie they won't be able to use it :-)

Hope this helps :-)

feha vision.to

Feha
A: 

For those reading through wanting to use this method in PHP scripts. Here is a working example using 256bit AES.

function encrypt($text, $salt) 
{ 
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
} 

function decrypt($text, $salt) 
{ 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $salt, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); 
}

Then to save the cookie

setcookie("PHPSESSION", encrypt('thecookiedata', 'longsecretsalt'));

and to read on the next page:

$data = decrypt($_COOKIE['PHPSESSION'], 'longsecretsalt');
Xeoncross