使用mcrypt进行PHP解密会返回难以理解的文本而不是原始明文

Ben*_*ene 1 php encryption mcrypt

我只是想加密和解密一个字符串.但是当我输出解密的字符串时,我只得到:

??
  ^????V??_??n?.ZZ?????:?2??
Run Code Online (Sandbox Code Playgroud)

我的代码:

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;
Run Code Online (Sandbox Code Playgroud)

任何想法都可能出错?

Art*_* B. 5

您在加密期间随机生成初始化向量(IV),这意味着密文将根据该IV进行随机化.解密时,需要提供与加密时使用的IV相同的IV.

由于IV不需要保密,您可以简单地将其添加到密文或以其他方式发送.在解密期间不要生成不同的IV.

如果您的明文较长(超过32个字节),您会看到前32个字节是错误的,但其余的都是正确的.如果您想了解更多关于CBC模式如何运作的信息,维基百科已经为您提供了帮助.


在加密期间,mcrypt对明文应用0x00字节的填充,因为CBC模式下的Rijndael工作在16字节的块上.您需要在解密后删除填充,因为它不是自动完成的:

return rtrim(mcrypt_decrypt(...), "\0");
Run Code Online (Sandbox Code Playgroud)

另外,不要忘记验证密文,因为padding-oracle攻击等攻击可以用来彻底解密某些密文.密文身份验证可以使用像GCM这样的身份验证模式,也可以通过密文生成的HMAC传递生成的身份验证标记来完成.

也可以看看


对于mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB)不应该包含的问题的评论中存在一些争议ECB,而是CBC模式,因为ECB模式不使用IV,但mcrypt很糟糕并且它很高兴地为CBC返回有效的IV(在这种情况下为32字节)尽管请求"IV for ECB"应该是0字节.

mcrypt是放弃软件,不应该再使用了.使用openssl/libsodium/defuse/...