Using this article as a guide, I was able to successfully replicate MySQL aes-128-ecb in PHP:
final class Encryption
{
const KEY = '36F3D40A7A41A827968BE75A87D60950';
public static function encrypt($string)
{
return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, self::getMySQLKey(self::KEY), self::getPaddedString($string), MCRYPT_MODE_ECB);
}
public static function decrypt($string)
{
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, self::getMySQLKey(self::KEY), $string, MCRYPT_MODE_ECB), "\x00..\x10");
}
public static function getMySQLKey($key)
{
$new_key = str_repeat(chr(0), 16);
for ($i = 0, $l = strlen($key); $i < $l; ++$i)
{
$new_key[$i % 16] = $new_key[$i % 16] ^ $key[$i];
}
return $new_key;
}
public static function getPaddedString($string)
{
return str_pad($string, (16 * (floor(strlen($string) / 16) + 1)), chr(16 - (strlen($string) % 16)));
}
}
As an example:
base64_encode(Encryption::encrypt('michael@example.com'))
SELECT TO_BASE64(AES_ENCRYPT('michael@example.com', '36F3D40A7A41A827968BE75A87D60950'));
However, I want to upgrade to using aes-256-cbc, but I'm having difficulties. I started by replacing MCRYPT_RIJNDAEL_128with MCRYPT_RIJNDAEL_256and MCRYPT_MODE_ECBby MCRYPT_MODE_CBCand used the constant KEYas the initialization vector:
public static function encrypt($string)
{
return mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::getMySQLKey(self::KEY), self::getPaddedString($string), MCRYPT_MODE_CBC, self::KEY);
}
public static function decrypt($string)
{
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, self::getMySQLKey(self::KEY), $string, MCRYPT_MODE_CBC, self::KEY), "\x00..\x10");
}
The problem is that now I get different values from PHP and MySQL:
base64_encode(Encryption::encrypt('michael@example.com'))
SELECT TO_BASE64(AES_ENCRYPT('michael@example.com', '36F3D40A7A41A827968BE75A87D60950', '36F3D40A7A41A827968BE75A87D60950'));
I am not sure where to come from here, so any help would be appreciated.
And just to make sure MySQL really uses the right encryption method:
SELECT @@session.block_encryption_mode