我只是想加密和解密一个字符串。但是当我输出解密的字符串时,我只得到:
��
^����V��_��n�.ZZ��Ǐ��:�2��
我的代码:
function encrypt($string, $secret_key = "ATRTHTRAGSFRSGTS") {
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
return mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $secret_key, $string, MCRYPT_MODE_CBC, $iv);
}
function decrypt($string, $secret_key = "ATRTHTRAGSFRSGTS") {
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $secret_key, $string, MCRYPT_MODE_CBC, $iv);
}
$text = 'This is a test.';
$enc = encrypt($text);
$dec = decrypt($enc);
echo $dec;
任何想法都可能出错?
答案 0 :(得分:5)
您在加密期间随机生成初始化向量(IV),这意味着密文将根据该IV进行随机化。解密时,您需要提供与加密时使用的相同的IV。
由于IV不需要保密,您可以简单地将其添加到密文或以其他方式发送。在解密过程中不要生成不同的IV。
如果您的明文较长(超过32个字节),您会看到前32个字节错误,但其余的都是正确的。如果您想进一步了解CBC模式的工作原理,Wikipedia可以帮助您解决问题。
在加密期间,mcrypt对明文应用0x00字节的填充,因为CBC模式下的Rijndael工作在16字节的块上。您需要在解密后删除填充,因为它不会自动完成:
return rtrim(mcrypt_decrypt(...), "\0");
另外,不要忘记验证密文,因为padding-oracle攻击等攻击可以用来彻底解密某些密文。密文证书可以使用经过身份验证的模式(如GCM)或通过HMAC传递密文生成的身份验证标记来完成。
另见
对mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB)
不应包含ECB
,而是CBC
模式的问题的评论中存在一些争议,因为ECB模式不使用IV,但是mcrypt是坏的,它很高兴地为CBC返回一个有效的IV(在这种情况下是32字节),尽管请求ECB" IV。应该是0字节。
mcrypt是放弃软件,不应该再使用了。使用openssl / libsodium / defuse /...