使用mcrypt_encrypt加密时报Encryption mode requires an initialization vector of size 16错误如何解决
问题原因
- CBC(密码分组链接)加密模式要求必须搭配初始化向量(IV)使用,你使用的
MCRYPT_RIJNDAEL_128算法对应IV长度要求为16字节,原代码未传入IV参数,因此触发警告且加密失败返回空。 - 额外注意:
mcrypt扩展自PHP 7.1起已被官方废弃,PHP 7.2及以上版本默认不再内置该扩展,生产环境更推荐使用openssl扩展实现对称加密。
修复方案(适配原有mcrypt逻辑)
首先生成符合要求的16字节随机IV,传入mcrypt_encrypt的第5个参数即可。解密时必须使用相同的IV才能正常解密,因此通常会将IV直接拼接在密文前存储/传输,解密时先取出前16位作为IV即可。
修复后的代码:
<?php $str = "hassan"; $key = "WKSaRVxscxa7eDrX0mLjU6OUphS6F1z0"; $block = 16; $pad = $block - (strlen($str) % $block); $str .= str_repeat(chr($pad), $pad); // 生成16字节随机IV $iv = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM); // 传入IV参数加密 $encrypted = base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_CBC, $iv)); var_dump($encrypted);
配套解密参考逻辑:
<?php $encrypted = base64_decode($加密后的字符串); // 取出前16位为IV $iv = substr($encrypted, 0, 16); // 剩余部分为密文 $ciphertext = substr($encrypted, 16); $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext, MCRYPT_MODE_CBC, $iv); // 移除PKCS7填充 $pad = ord($decrypted[$strlen = strlen($decrypted) - 1]); $decrypted = substr($decrypted, 0, $strlen - $pad);
更推荐的openssl实现方案(兼容PHP7+所有版本)
如果你的运行环境已经不支持mcrypt,可直接使用openssl扩展实现同等的AES-128-CBC加密,无需手动处理填充:
<?php $str = "hassan"; $key = "WKSaRVxscxa7eDrX0mLjU6OUphS6F1z0"; $iv = openssl_random_pseudo_bytes(16); // 加密 $encrypted = base64_encode($iv . openssl_encrypt($str, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv)); var_dump($encrypted); // 解密逻辑 $encrypted = base64_decode($encrypted); $iv = substr($encrypted, 0, 16); $ciphertext = substr($encrypted, 16); $decrypted = openssl_decrypt($ciphertext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); var_dump($decrypted);
内容的提问来源于stack exchange,提问作者Muhammad Hassan Javed
相关产品推荐
相关产品推荐

