我正在尝试编写一个简单的mcrypt三重加密和解密函数(以下代码取自http://php.net/manual/en/function.mcrypt-encrypt.php并已修改)。
<?php
class Cipher {
private $securekey, $iv;
private $val;
function __construct($textkey) {
$this->securekey = $textkey;
$this->iv = mcrypt_create_iv(24);
}
function decrypt_hex($input){
$bin = hex2bin($input);
return trim(mcrypt_decrypt("tripledes", $this->securekey, $bin, MCRYPT_MODE_ECB, $this->iv));
}
function encrypt_hex($input){
$this->val = mcrypt_encrypt("tripledes", $this->securekey, $input, MCRYPT_MODE_ECB, $this->iv);
return strtoupper(bin2hex($this->val));
}
}
$cipher = new Cipher('123456789012345678901234');
$text = "2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D4B97BD1710125FFD";
echo "Decrypting ===== $text<br/>";
$dec = $cipher->decrypt_hex($text);
echo "Decrypted = $dec<br/>";
$text = "2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D72FD337F5B6B334B";
echo "Decrypting ===== $text<br/>";
$dec = $cipher->decrypt_hex($text);
echo "Decrypted = $dec<br/>";
?>
但是,我发现可以从两个不同的加密十六进制字符串解密相同的字符串(在代码末尾显示的情况)。
这是正常的吗?
有多少这样的字符串存在?我怎么才能找到?
在第一个解密字符串的末尾似乎有一些隐藏的字符。它们不会出现在html中(可能在编辑文本模式中可见,由html sanitizer清理:()。这有什么不同吗?
在PHP 5.6.8中输出上述脚本:
Decrypting ===== 2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D4B97BD1710125FFD
Decrypted = Beli IM3 085728317777 30000
Decrypting ===== 2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D72FD337F5B6B334B
Decrypted = Beli IM3 085728317777 30000
答案 0 :(得分:3)
您只更改了密文的结尾。这包含最后一块加密明文。但是,通常明文不会在块边界上结束。在这种情况下,PHP将执行零填充,直到达到块边界。 trim
函数删除了这些零字节(您应该使用rtrim
并仅删除\0
个字节)。
现在,如果更改最后一个块的字节,则解密将导致随机字节。该块可能会开始 - 偶然 - 使用相同的字符,然后是任何其他 - 可能是不可打印的 - 字符。在这种情况下,屏幕上打印的字符串可能会显示相同的内容。
你应该真的:
MCRYPT_RIJNDAEL_128
); 答案 1 :(得分:1)
它们不同,请尝试以下操作:var_dump($dec1 === $dec2);
返回 false 。
同样echo strlen($dec1);
返回 32 ,echo strlen($dec2);
返回 27 。
更新:
发现,他们有不同的编码。因此它们有不同的尺寸:
var_dump(mb_detect_encoding($dec1));
返回字符串(5)“ UTF-8 ”。当var_dump(mb_detect_encoding($dec2));
返回字符串(5)“ ASCII ”时。