【问题标题】:PHP 3DES EncryptionPHP 3DES 加密
【发布时间】:2017-05-18 22:05:43
【问题描述】:

这是我的代码

 $key = pack('H*', "11223344556677881122334455667788");
 $plaintext = pack('H*', "0000000000000000");

 $ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $plaintext, MCRYPT_MODE_ECB);
 echo bin2hex($ciphertext);

但我得到的结果是 8ca64de9c1b123a7 与 this site 不同

6FB23EAD0534752B 这是我想要的

谁能解释为什么我得到与该网站不同的密码文本?

【问题讨论】:

  • According to this comment at php.net,mcrypt 的 3DES 只接受 192 位密钥。您的密钥是 128 位。在$key = pack('H*', "11223344556677881122334455667788"); 之后,尝试添加$key .= substr($key,0,8); 看看是否有帮助。 (我无法测试,因为我没有在任何地方安装 mcrypt。)
  • @squeamishossifrage 在 Java 上测试,我使用密钥 112233445566778811223344556677880000000000000000 得到了结果。 mcrypt 无疑是我遇到过的最糟糕的库。
  • 我尝试在 DES 中加密,并获得正确的密码文本,但收到 PHP 警告:对于此算法,密钥大小太大。那么这一方是怎么做的呢?

标签: php encryption cryptography tripledes


【解决方案1】:

mcrypt 有 - 或者更确切地说有 - 如果大小不正确,用零填充任何东西的讨厌习惯。更糟糕的是,它还通过删除字节将键切割成正确的大小。

作为 squeamish ossifrage commented mcrypt 似乎只支持 3 键三重 DES。这还不错,直到您注意到它会愉快地接受 16 字节的 2 密钥三重 DES 密钥,然后用零填充它以使其成为 3 密钥三重 DES 密钥。它当然应该失败,而新版本的 mcrypt 实际上应该这样做。

不过,您可以使用 3 键三重 DES 创建相同的结果。 2 密钥三重 DES 只是将第一个密钥重用于最后一个密钥,因此复制前 8 个字节并将其附加到密钥的末尾会得到正确的结果(同样,正如 squeamish 已经指出的那样)。

最好使用另一个加密库来获得正确的结果。 mcrypt(底层 C 库)已经有 8 年左右(并且还在继续)没有维护,而且非常糟糕。


Java 中的示例(也不完全支持 2 键三重 DES):

    byte[] pt = new byte[16];
    SecretKeyFactory fact = SecretKeyFactory.getInstance("DESede");
    Cipher desEDE = Cipher.getInstance("DESede/ECB/NoPadding");

    {
        // usual 2-key triple DES:
        byte[] keyData = Hex.decode("112233445566778811223344556677881122334455667788");
        SecretKey generatedSecret = fact.generateSecret(new SecretKeySpec(keyData, "DESede"));
        desEDE.init(Cipher.ENCRYPT_MODE, generatedSecret);
        byte[] ct = desEDE.doFinal(pt);
        System.out.println(Hex.toHexString(ct)); // result: 6FB23EAD0534752B 
    }

    {
        // "zero padded" 2-key triple DES:
        byte[] keyData = Hex.decode("112233445566778811223344556677880000000000000000");
        SecretKey generatedSecret = fact.generateSecret(new SecretKeySpec(keyData, "DESede"));
        desEDE.init(Cipher.ENCRYPT_MODE, generatedSecret);
        byte[] ct = desEDE.doFinal(pt);
        System.out.println(Hex.toHexString(ct)); // result: 8ca64de9c1b123a7 
    }

注意事项:

  • 您的 DES 密钥不是完全有效的,因为每个字节的奇偶校验位设置不正确(但是,那些未在 DES 计算中使用);
  • 最好使用 AES 和经过身份验证的密码模式,而不是不安全的 ECB 模式。

【讨论】:

  • 感谢您向我解释。现在我明白了。
  • newer in newer versions of mcrypt 应该用引号引起来。 :)
  • @ArtjomB。是的,好吧,他们现在至少需要 PHP mcrypt wrapper 中正确的密钥大小。
猜你喜欢
  • 2016-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 2015-10-04
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多