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 模式。
这是我的代码
$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
不过,您可以使用 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 模式。