mcrypt_encrypt
is deprecated, so here's a solution that's capable of falling back on openssl_encrypt
instead. Truthfully, I don't know how all of it works. It's kind of a composite of some solutions I found regarding replicating MySQL's AES_ENCRYPT
in mcrypt_encrypt
, and then replicating mcrypt_encrypt
in openssl_encrypt
. The generation of the key from what would otherwise be used as the salt arguments in AES_ENCRYPT
, as well as understanding which cypher to use when, is a little beyond me. But I can say these functions have been time-tested to be functionally identical to their MySql counterparts.
if (!function_exists('mysql_aes_key')) {
/**
* @param string $key
* @return string
*/
function mysql_aes_key($key)
{
$new_key = str_repeat(chr(0), 16);
for ($i = 0, $len = strlen($key); $i < $len; $i++) {
$new_key[$i % 16] = $new_key[$i % 16] ^ $key[$i];
}
return $new_key;
}
}
if (!function_exists('aes_encrypt')) {
/**
* @param string $val
* @param string $cypher
* @param bool $mySqlKey
* @return string
* @throws \BadFunctionCallException
*/
function aes_encrypt($val, $cypher = null, $mySqlKey = true)
{
$salt = getenv('SALT') ?: '1234567890abcdefg';
$key = $mySqlKey ? mysql_aes_key($salt) : $salt;
if (function_exists('mcrypt_encrypt')) {
$cypher = (!$cypher || $cypher == strtolower('aes-128-ecb')) ? MCRYPT_RIJNDAEL_128 : $cypher;
$pad_value = 16 - (strlen($val) % 16);
$val = str_pad($val, (16 * (floor(strlen($val) / 16) + 1)), chr($pad_value));
return @mcrypt_encrypt($cypher, $key, $val, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_DEV_URANDOM));
} elseif (function_exists('openssl_encrypt')) {
//TODO: Create a more comprehensive map of mcrypt <-> openssl cyphers
$cypher = (!$cypher || $cypher == MCRYPT_RIJNDAEL_128) ? 'aes-128-ecb' : $cypher;
return openssl_encrypt($val, $cypher, $key, true);
}
throw new \BadFunctionCallException('No encryption function could be found.');
}
}
if (!function_exists('aes_decrypt')) {
/**
* @param string $val
* @param string $cypher
* @param bool $mySqlKey
* @return string
* @throws \BadFunctionCallException
*/
function aes_decrypt($val, $cypher = null, $mySqlKey = true)
{
$salt = getenv('SALT') ?: '1234567890abcdefg';
$key = $mySqlKey ? mysql_aes_key($salt) : $salt;
if (function_exists('mcrypt_decrypt')) {
$cypher = (!$cypher || $cypher == strtolower('aes-128-ecb')) ? MCRYPT_RIJNDAEL_128 : $cypher;
$val = @mcrypt_decrypt($cypher, $key, $val, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_DEV_URANDOM));
return rtrim($val, chr(0)."..".chr(16));
} elseif (function_exists('openssl_decrypt')) {
//TODO: Create a more comprehensive map of mcrypt <-> openssl cyphers
$cypher = (!$cypher || $cypher == MCRYPT_RIJNDAEL_128) ? 'aes-128-ecb' : $cypher;
return openssl_decrypt($val, $cypher, $key, true);
}
throw new \BadFunctionCallException('No decryption function could be found.');
}
}
So...
putenv('SALT=1234567890abcdefg');
aes_encrypt('some_value') === SELECT AES_ENCRYPT('some_value', '1234567890abcdefg')
aes_decrypt('some_encrypted_value') === SELECT AES_DECRYPT('some_encrypted_value', '1234567890abcdefg')
I tested these by encrypting a value with the php function, and decrypting it with the MySQL one, and visa-versa.