PHP 3DES 加密

PHP 3DES Encryption

这是我的代码

 $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 这就是我想要的

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

mcrypt 有——或者更确切地说,有——如果大小不正确就用零填充任何东西的恶习。更糟糕的是,它还通过删除字节将密钥切割为正确的大小。

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

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

最好使用另一个加密库来获得正确的结果。 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 模式。