Monday, July 15, 2013

PHP-Encrypt-Decrypt: Binary vs. Hex

This PHP script makes an interesting mistake. It attempts to derive a key from a password using md5, but it uses the hex-encoded MD5 output as the key, not the raw binary output. The hexadecimal string is passed to the mcrypt_encrypt() function, which interprets the 32-character hex string as a 256-bit key, even though it's really only 128 bits.

The author's intention was probably to use AES. In PHP, MCRYPT_RIJNDAEL_256 refers to the 256-bit block variant of Rijndael, not the 128-bit block version that was selected for AES. The key size of 128, 192, or 256 bits is determined by the length of the key parameter.

 $SECRET_KEY = 'YOUR SECRET KEY';  
 // ...  
 $encrypted_i = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($SECRET_KEY), $value, MCRYPT_MODE_CBC, md5(md5($SECRET_KEY))));  

Lessons Learned:
  • Specify crypto parameters in the right format. Look at the output of the functions you use to make sure it's in the format you expect.
  • Use key stretching (PBKDF2) to derive a key from a password, not MD5.
  • Generate a random IV at the time of encryption. Do not derive it from the key.
  • Use test vectors to ensure you are using the correct primitives.

No comments:

Post a Comment