0

I have a below PHP function that I want to implement in Java with no luck, I'm not able to obtain the same output:

function encryptText( $plainText, $key )
{
    $mcopen = mcrypt_module_open (MCRYPT_TripleDES, "", MCRYPT_MODE_ECB,"");
    $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($mcopen), MCRYPT_RAND);
    $td = mcrypt_module_open('tripledes', '', 'ecb', '');
    $cryptedHash = '';

    if (mcrypt_generic_init($td, $key, $iv) != -1)
    {
        $cryptedHash = mcrypt_generic($td, $plainText);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
    }
    return base64_encode($cryptedHash);
 }

This is my java code found here :

public static String encrypt(String message, String key) throws Exception {
    final MessageDigest md = MessageDigest.getInstance("md5");
    final byte[] digestOfPassword = md.digest(key.getBytes("utf-8"));
    final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
    for (int j = 0, k = 16; j < 8;) {
        keyBytes[k++] = keyBytes[j++];
    }

    final SecretKey keyz = new SecretKeySpec(keyBytes, "DESede");
    final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
    final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, keyz, iv);

    final byte[] plainTextBytes = message.getBytes("utf-8");
    final byte[] cipherText = cipher.doFinal(plainTextBytes);
    final String encodedCipherText = new   sun.misc.BASE64Encoder().encode(cipherText);

    return encodedCipherText;
}
Community
  • 1
  • 1
Mustapha K.
  • 1
  • 1
  • 3

2 Answers2

3

You have a couple of problems.

  • Since you want to use ECB mode, then you need to specify ECB mode. CBC is a different mode.

  • You're not running your key through MD5 in the PHP code, so you shouldn't do that in Java.

  • A block cipher in ECB or CBC mode needs a padding in order to encrypt arbitrary messages. Mcrypt uses zero padding by default, but you're specifying PKCS#5 padding in Java. Since the default Sun providers doesn't implement ZeroPadding, you will either need to implement it yourself by specifying "NoPadding" and implementing the zero padding yourself, or use the BouncyCastle provider: Cipher.getInstance("DESede/ECB/ZeroPadding", "BC").


Other considerations:

Never use ECB mode. It's not semantically secure. If you encrypt the same message under the same key twice, the attacker can easily see that you encrypted the same message (or same part of the message) again.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Thanks for this answer. I'll try to implement your recommandations. For the ECB mode I know that it is not very secure, but this is what is actualy implemented in the php side (partner). – Mustapha K. Sep 14 '15 at 10:40
0

Solved, the solution :

public static String cryptBC(String data, String key) throws Exception{
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    byte[] input = data.getBytes();
    byte[] keyBytes = key.getBytes() ;   
    SecretKeySpec skey = new SecretKeySpec(keyBytes, "DESede");
    Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding", "BC");

    if(input.length % 8 != 0){ 
        byte[] padded = new byte[input.length + 8 - (input.length % 8)];
        System.arraycopy(input, 0, padded, 0, input.length);
        input = padded;
    }
    System.out.println("input : " + new String(input));
    cipher.init(Cipher.ENCRYPT_MODE, skey);
    byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
    int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
    ctLength += cipher.doFinal(cipherText, ctLength);

    return new String(Base64.encodeBase64(cipherText));
}
Mustapha K.
  • 1
  • 1
  • 3