View source
<?php
$plugin = encrypt_mcrypt_aes_cbc_encrypt_encryption_methods();
function encrypt_mcrypt_aes_cbc_encrypt_encryption_methods() {
return array(
'title' => t('Mcrypt AES (CBC Mode)'),
'description' => t("Uses PHP's Mcrypt extension and AES in CBC mode. The key MUST be 16, 24, or 32 bytes."),
'encrypt callback' => '_encrypt_encryption_methods_mcrypt_aes_cbc',
'dependency callback' => '_encrypt_mcrypt_extension_is_present',
);
}
function _encrypt_encryption_mcrypt_module_open($algorithm, $algorithm_directory, $mode, $mode_directory) {
if (!function_exists('mcrypt_module_open')) {
throw new Exception('mcrypt_module_open() does not exist.');
}
$result = mcrypt_module_open($algorithm, $algorithm_directory, $mode, $mode_directory);
if (!$result) {
throw new Exception('mcrypt_module_open() returned FALSE.');
}
return $result;
}
function _encrypt_encryption_methods_mcrypt_aes_cbc($op, $text, $key, $options = array(), $method_settings = array()) {
$disable_base64 = array_key_exists('base64', $options) && $options['base64'] == FALSE;
$mcrypt = _encrypt_encryption_mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$iv_size = mcrypt_enc_get_iv_size($mcrypt);
$block_size = mcrypt_enc_get_block_size($mcrypt);
$hash_function = 'sha256';
$allowed_key_sizes = array(
16,
24,
32,
);
$key_size = strlen($key);
$salt_size = 32;
$hmac_size = 32;
if (empty($key) || !in_array($key_size, $allowed_key_sizes)) {
$t_args = array(
'@action' => $op == 'decrypt' ? t('Decryption') : t('Encryption'),
);
drupal_set_message(t('@action failed because the key is not the right size.', $t_args), 'error');
watchdog('encrypt', '@action failed because the key is not the right size.', $t_args, WATCHDOG_CRITICAL);
throw new Exception(t('@action failed because the key is not the right size.', $t_args));
}
if ($op == 'decrypt') {
if (!$disable_base64) {
$text = base64_decode($text);
}
$hmac = substr($text, 0, $hmac_size);
$text = substr($text, $hmac_size);
$salt = substr($text, 0, $salt_size);
$esalt = substr($salt, 0, strlen($salt) / 2);
$asalt = substr($salt, strlen($salt) / 2);
$akey = _encrypt_encryption_methods_mcrypt_aes_cbc_hkdf($hash_function, $key, $key_size, $asalt);
$calculated_hmac = _encrypt_encryption_methods_mcrypt_aes_cbc_hkdf($hash_function, $text, $hmac_size, $akey);
if ($calculated_hmac != $hmac) {
drupal_set_message(t('Decryption failed because the HMAC could not be validated.'), 'error');
watchdog('encrypt', 'Decryption failed because the HMAC could not be validated.', array(), WATCHDOG_CRITICAL);
throw new Exception(t('Decryption failed because the HMAC could not be validated.'));
}
$text = substr($text, $salt_size);
$iv = substr($text, 0, $iv_size);
$text = substr($text, $iv_size);
$ekey = _encrypt_encryption_methods_mcrypt_aes_cbc_hkdf($hash_function, $key, $key_size, $esalt);
mcrypt_generic_init($mcrypt, $ekey, $iv);
$processed_text = mdecrypt_generic($mcrypt, $text);
mcrypt_generic_deinit($mcrypt);
$pad = ord($processed_text[strlen($processed_text) - 1]);
$processed_text = substr($processed_text, 0, -$pad);
mcrypt_module_close($mcrypt);
}
else {
$iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
$salt = drupal_random_bytes($salt_size);
$esalt = substr($salt, 0, strlen($salt) / 2);
$asalt = substr($salt, strlen($salt) / 2);
$ekey = _encrypt_encryption_methods_mcrypt_aes_cbc_hkdf($hash_function, $key, $key_size, $esalt);
mcrypt_generic_init($mcrypt, $ekey, $iv);
$pad = $block_size - strlen($text) % $block_size;
$processed_text = mcrypt_generic($mcrypt, $text . str_repeat(chr($pad), $pad));
$processed_text = $salt . $iv . $processed_text;
$akey = _encrypt_encryption_methods_mcrypt_aes_cbc_hkdf($hash_function, $key, $key_size, $asalt);
$hmac = _encrypt_encryption_methods_mcrypt_aes_cbc_hkdf($hash_function, $processed_text, $hmac_size, $akey);
$processed_text = $hmac . $processed_text;
if (!$disable_base64) {
$processed_text = base64_encode($processed_text);
}
mcrypt_module_close($mcrypt);
}
return $processed_text;
}
function _encrypt_encryption_methods_mcrypt_aes_cbc_hkdf($hash_function, $ikm, $length, $salt) {
$key = hash_hmac($hash_function, $ikm, $salt, TRUE);
$key = substr($key, 0, $length);
return $key;
}
function _encrypt_mcrypt_extension_is_present() {
$errors = array();
if (!function_exists('mcrypt_encrypt')) {
$errors[] = t('Mcrypt library not installed.');
}
return $errors;
}