I am thinking about making the switch to storing session data in encrypted cookies rather than somewhere on my server. While this will result in more bandwidth used for each request - it will save extra database server load and storage space.
Anyway, I plan on encrypting the cookie contents using RIJNDAEL 256.
function encrypt($text, $key)
{
return mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$key,$text,MCRYPT_MODE_ECB,mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256,MCRYPT_MODE_ECB),MCRYPT_RAND));
}
Which in use would produce something like this (base64 encoded for display)
print base64_encode(encrypt('text', 'key'));
7s6RyMaYd4yAibXZJ3C8EuBtB4F0qfJ31xu1tXm8Xvw=
I'm not worried about a single users cookie being compromised as much as I am worried that an attacker would discover the key
and be able to construct any session for any user since they know what I use to sign the data.
Is there a way I can verify estimated cracking times in relation to the parameters used? Or is there a standard measure of time in relation to the size of the text or key used?
I heard someone say that the keys needed to exceed 256bits themselves to be safe enough to be used with RIJNDAEL. I'm also wondering if the length of the text encrypted needs to be a certain length so as not to give away the key.
The data will generally be about 200 characters
a:3{s:7:"user_id";i:345;s:5:"token";s:32:"0c4a14547ad221a5d877c2509b887ee6";s:4:"lang";s:2:"en";}
So is this safe?
Avoid using ECB. It can reveal information about what's encrypted. Any two blocks with the same plaintext will have the same ciphertext. CBC would avoid this, but requires an IV to be generated or saved.
Avoid simply saving a key and IV. Generate a 256 bit master key using a cryptographically strong random number generator and save that into you application somewhere safe. Use that to generate session keys for use in encryption. The IV can be derived from the session key. When generating the session key include any and all available data that can be used to narrow the scope of the session key. (e.g. include the scope the cookie, the remote host address, a random nounce stored with the encrypted data, and/or a user ID if it isn't within the encrypted data)
Depending on how the data is to be used you may have to include a MAC. ECB and CBC are not designed to detect any changes to the ciphertext, and such changes will result in garbage in plaintext. You might want to include an HMAC with the encrypted data to allow you to authenticate it before taking it as canon. A session HMAC key must be derived from the session encryption key. Alternatively, you could use PCBC mode. PCBC was made to detect changes in the ciphertext, but its ability to do so is limited by the size of the padding, witch is dependent on the data that is encrypted, and not all crypto APIs will have it as an option.
Once you have gone so far as to include a MAC, then you should consider taking steps against replay attacks. Any time someone can resend old data within the scope of a session is a chance for a replay attack. Making a session key usage as narrow as possible without causing issues for the user is one way to thwart replay attacks. Another thing you could do is include a date and time into the encrypted data to create a window for while the data is to be considered valid.
In summery, protecting the key is just the tip of the iceburg.