PHP等效于Java Triple DES加密/解密

我试图使用PHP mcrypt函数解密由Java Triple DES函数加密的密钥,但没有运气。 在下面找到java代码

import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class Encrypt3DES { private byte[] key; private byte[] initializationVector; public Encrypt3DES(){ } public String encryptText(String plainText, String key) throws Exception{ //---- Use specified 3DES key and IV from other source -------------- byte[] plaintext = plainText.getBytes(); byte[] myIV = key.getBytes(); byte[] tdesKeyData = {(byte)0xA2, (byte)0x15, (byte)0x37, (byte)0x08, (byte)0xCA, (byte)0x62, (byte)0xC1, (byte)0xD2, (byte)0xF7, (byte)0xF1, (byte)0x93, (byte)0xDF, (byte)0xD2, (byte)0x15, (byte)0x4F, (byte)0x79, (byte)0x06, (byte)0x67, (byte)0x7A, (byte)0x82, (byte)0x94, (byte)0x16, (byte)0x32, (byte)0x95}; Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding"); SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede"); IvParameterSpec ivspec = new IvParameterSpec(myIV); c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec); byte[] cipherText = c3des.doFinal(plaintext); sun.misc.BASE64Encoder obj64=new sun.misc.BASE64Encoder(); return obj64.encode(cipherText); } public String decryptText(String encryptText, String key) throws Exception{ byte[] initializationVector = key.getBytes(); byte[] tdesKeyData = {(byte)0xA2, (byte)0x15, (byte)0x37, (byte)0x08, (byte)0xCA, (byte)0x62, (byte)0xC1, (byte)0xD2, (byte)0xF7, (byte)0xF1, (byte)0x93, (byte)0xDF, (byte)0xD2, (byte)0x15, (byte)0x4F, (byte)0x79, (byte)0x06, (byte)0x67, (byte)0x7A, (byte)0x82, (byte)0x94, (byte)0x16, (byte)0x32, (byte)0x95}; byte[] encData = new sun.misc.BASE64Decoder().decodeBuffer(encryptText); Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede"); IvParameterSpec ivspec = new IvParameterSpec(initializationVector); decipher.init(Cipher.DECRYPT_MODE, myKey, ivspec); byte[] plainText = decipher.doFinal(encData); return new String(plainText); } } 

我想编写一个等同于上面的decryptText Java函数的PHP函数。 我发现难以生成由加密的Java代码生成的确切IV值,这是解密所需的。

这是你的Java代码的PHP等价物(我从mcrypt参考的评论20-Sep-2006 07:56复制了PKCS#5-padding)

 function encryptText($plainText, $key) { $keyData = "\xA2\x15\x37\x08\xCA\x62\xC1\xD2" . "\xF7\xF1\x93\xDF\xD2\x15\x4F\x79\x06" . "\x67\x7A\x82\x94\x16\x32\x95"; $padded = pkcs5_pad($plainText, mcrypt_get_block_size("tripledes", "cbc")); $encText = mcrypt_encrypt("tripledes", $keyData, $padded, "cbc", $key); return base64_encode($encText); } function decryptText($encryptText, $key) { $keyData = "\xA2\x15\x37\x08\xCA\x62\xC1\xD2" . "\xF7\xF1\x93\xDF\xD2\x15\x4F\x79\x06" . "\x67\x7A\x82\x94\x16\x32\x95"; $cipherText = base64_decode($encryptText); $res = mcrypt_decrypt("tripledes", $keyData, $cipherText, "cbc", $key); $resUnpadded = pkcs5_unpad($res); return $resUnpadded; } function pkcs5_pad ($text, $blocksize) { $pad = $blocksize - (strlen($text) % $blocksize); return $text . str_repeat(chr($pad), $pad); } function pkcs5_unpad($text) { $pad = ord($text{strlen($text)-1}); if ($pad > strlen($text)) return false; if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false; return substr($text, 0, -1 * $pad); } 

但是你应该注意一些问题:

  • 在Java代码中,您调用String.getBytes()而不指示编码。 如果明文包含非ASCII字符(如变音符号),则会使您的代码不可移植,因为Java使用系统默认字符集。 如果你可以改变,我当然会这样做。 我建议你在双方都使用utf-8(Java和PHP)。
  • 您已对密码密钥进行了硬编码,并将IV用作“密钥”。 我绝不是一个加密专家,但对我而言,它只是感觉不对,可能会造成巨大的安全漏洞。
  • 创建一个随机IV,并在消息的开头或结尾处连接它。 由于IV的大小是AFAIK,等于你的密码的块大小,你只需从开头或结尾删除那么多字节,并且很容易将IV与消息分开。
  • 至于密钥,最好使用某种密钥派生方法从“人工生成”密码生成具有正确大小的密钥。

当然,如果您必须满足某些要求,则无法更改方法。

答案差不多好! 只需反转$keyData$key

 $encText = mcrypt_encrypt("tripledes", $keyData, $padded, "cbc", $key); 

 $res = mcrypt_decrypt("tripledes", $keyData, $cipherText, "cbc", $key); 

否则你将始终使用相同的3DES键。 最好将$keyData重命名为$iv

无论如何,非常感谢Java示例和Php-Java翻译。