PHP equivalent for Java Triple DES encryption / decryption

I am trying to decrypt a key encrypted with the Java Triple DES function using the PHP mcrypt function, but no luck. Find below Java code

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); } } 

I want to write a PHP function equivalent to the decryptText Java function described above. I find it difficult to generate the exact IV value generated by the Java encryption code that is required for decryption.

+6
source share
2 answers

This is the PHP equivalent of your Java code (I copied PKCS # 5-padding from a comment 20-Sep-2006 07:56 mcrypt link )

 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); } 

But there are some issues you should be aware of:

  • In Java code, you call String.getBytes() without specifying an encoding. This makes your code not portable if your plain text contains non-ASCII characters, such as umlauts, because Java uses the default character set. If you can change this, I would do it. I recommend using utf-8 on both sides (Java and PHP).
  • You have a hard-coded encryption key and use IV as the "key". I'm by no means a crypto expert, but for me he just feels wrong and can open up a huge security leak.
  • Create a random IV and simply connect it at the beginning or at the end of your message. Since the size of IV is equal to AFAIK, equal to the block size of your cipher, you simply delete as many bytes from the beginning or end and easily separate IV from the message.
  • As for the key, it is best to use some method to generate the key with the correct size from "human-generated human". "

Of course, if you need to fulfill some of the specified requirements, you will not be able to change your method.

+9
source

The answer is almost good! Just change $keyData and $key to

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

and

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

otherwise, you will always use the same 3DES key. And it's better to rename $keyData to $iv .

Anyway, thanks for the Java sample and the translation of Php-Java.

0
source

Source: https://habr.com/ru/post/903890/


All Articles