Showing posts with label PHP. Show all posts
Showing posts with label PHP. Show all posts

Monday, June 9, 2008

Securing cookies : a PHP implementation

Update: French version here.

Note for newcomers : you should first read the previous post introducing secure cookies : Security, Cookies and the REST.

So... where were we ? There is a secure protocol for cookies (see Alex X. Liu's paper for details) :

Cookie value =
username|expiration time|(data)k|HMAC(username|expiration time|data|SSL session key, k)
Where :
  • username is the username (or an unique identifier)
  • expiration time : the cookie's expiration time
  • (data)k is the result of a symmetric cryptographic (ex: Rijndael) function on data with key k.
  • data is the data you want to store in the cookie
  • k is the result of HMAC(username|expiration time, sk)
  • sk is the server's secret key
  • SSL session key is the SSL session key.

This protocol is secure :

  • It protects your cookie against replay attacks : SSL session key is unique to your SSL session. So a malicious user can't send the same cookie in another SSL session, it'll be invalid.
  • It protects the data confidentiality with a symmetric cryptographic function : data is stored encrypted
  • It protects the data integrity with an HMAC function
  • It protects your secret key against volume attacks

But it needs some flexibility for a common usage :

  1. SSL Feature is cool, it protects you against replay attacks, but :
    • Maybe you have no HTTPS access to your application
    • Cookie's lifetime is limited to the SSL session lifetime
  2. Data encryption is cool, but maybe you're not interested in this feature. If you are not, it expands the size of the cookie for nothing. For example: if data is encrypted with with Rijndael/256 bits key, the encrypted value will be at least 32 byte long, even if your data is 1 byte long

So, it may be cool to have a configurable class to manage secure cookies. By configurable, I mean to be able to :

  • enable/disable SSL feature
  • enable/disable the data encryption feature
  • choose the encryption algorithm

I've done a PHP class which have all these functionality. You can download it here.

Usage :

Initialization

include('BigOrNot_CookieManager.php');

$secretKey = 'Cei4Wai4ohcoo3daeHooFiek5Nah3Eet';
$manager = new BigOrNot_CookieManager($secretKey);

All you have to do is to provide a secret key. To generate a key you can use this shell command :

pgwen -sy 65

The default configuration is :

  • High confidentiality (data encryption) : enabled option name : high_confidentiality (bool)
  • Cipher : MCRYPT_RIJNDAEL_256 (Rijndael 256) option name : mcrypt_algorithm (see mcrypt documentation)
  • Mode : MCRYPT_MODE_CBC (CBC) option name : mcrypt_mode (see mcrypt_documentation)
  • SSL session key : disabled option name : enable_ssl (bool)

You can (optionally) give a second argument to the constructor to configure the class. For example, if you want to disable data encryption you can do that :

include('BigOrNot_CookieManager.php');

$secretKey = 'Cei4Wai4ohcoo3daeHooFiek5Nah3Eet';
$config = array('high_confidentiality' => false);
$manager = new BigOrNot_CookieManager($secretKey, $config);

Set a secure cookie

$expire = time() + 86400;
$value = $manager->setCookie('cookieName', 'value', 'username');
Read source for more details on possible arguments. (You can give all regular setcookie() arguments)

Read/verify a cookie value

$value = $manager->getCookieValue('cookieName');
If cookie is invalid, it will be deleted automatically. If you don't like this behaviour, you can give "false" as a second argument.

Delete a cookie

$manager->deleteCookie('cookieName');

Enjoy ! Source file is commented if you need more informations. If you have questions, remarks, bug reports, post a comment :)

Note: There is a class to use the same protocol with Django (Python) here.