PHP is sometimes really dumb.

While working on a library for Weave’s OAuth implementation (so 3rd party developers don’t have to understand the nitty-gritty of OAuth and can instead use a simple library in their favorite programming language), I ran across the need to do AES-256 decryption in PHP.

The best (and fastest) method would be to use PHP’s mcrypt extension, but mcrypt lists support for ‘Rijndael’ and not ‘AES’. They’re both practically the same, except for the very small difference of the IV (initialization vector) being different sizes. In Rijndael, the IV is always the same size as that of the key, but in AES, the IV is always 16 bytes.

Weave uses AES-256, which means we have a 32 byte key, and a 16 byte IV. mcrypt implements Rijndael, so my first try:

<?php
// $key is 32 bytes long
$iv = 'sixteenbyteslong';
$td = mcrypt_module_open(
  MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, ''
);
mcrypt_generic_init($td, $key, $iv);
?>

failed with:

Warning: mcrypt_generic_init(): Iv size incorrect;
supplied length: 16, needed: 32 in aes.php on line 26

Here’s the workaround:

<?php
$td = mcrypt_module_open(
  MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''
);
mcrypt_generic_init($td, $key, $iv);
?>

That’s right - you call mcrypt_module_open with Rijndael-128 instead of 256, but still pass a 32 byte key to mcrypt_generic_init and be on your merry way.

WTF, but I’m happy that it atleast works.