为什么我的两个加密的十六进制字符串解密为相同的字符串?

时间:2015-05-08 15:19:49

标签: php encryption mcrypt des

我正在尝试编写一个简单的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/>";

?>

但是,我发现可以从两个不同的加密十六进制字符串解密相同的字符串(在代码末尾显示的情况)。

  1. 这是正常的吗?

  2. 有多少这样的字符串存在?我怎么才能找到?

  3. 在第一个解密字符串的末尾似乎有一些隐藏的字符。它们不会出现在html中(可能在编辑文本模式中可见,由html sanitizer清理:()。这有什么不同吗?

  4. 在PHP 5.6.8中输出上述脚本:

    Decrypting ===== 2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D4B97BD1710125FFD
    Decrypted = Beli IM3 085728317777 30000
    Decrypting ===== 2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D72FD337F5B6B334B
    Decrypted = Beli IM3 085728317777 30000
    

2 个答案:

答案 0 :(得分:3)

您只更改了密文的结尾。这包含最后一块加密明文。但是,通常明文不会在块边界上结束。在这种情况下,PHP将执行零填充,直到达到块边界。 trim函数删除了这些零字节(您应该使用rtrim并仅删除\0个字节)。

现在,如果更改最后一个块的字节,则解密将导致随机字节。该块可能会开始 - 偶然 - 使用相同的字符,然后是任何其他 - 可能是不可打印的 - 字符。在这种情况下,屏幕上打印的字符串可能会显示相同的内容。

你应该真的:

  • 使用AES(MCRYPT_RIJNDAEL_128);
  • 执行PKCS#7兼容填充;
  • 使用CBC模式加密随机IV;
  • 将IV加密到密文;
  • 添加身份验证标记(使用HMAC-SHA-1);
  • 可能编码IV +密文+标签。

答案 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 ”时。