2
votes

I have a problem with ecrypting data using AES-128/ecb/PKCS5Padding+base64. I am using the following code to encrypt my data:

String input = "{\"action\":\"getQuestion\"}";
String key = "4288f0b8060ca1b682bf795f2617cfdc";
byte[] data = input.getBytes();
byte[] encrypted = null;
byte[] keyBytes = new BigInteger(key, 16).toByteArray();
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
encrypted = cipher.doFinal(data);
System.out.println(Base64.encodeBytes(encrypted));

I receive 6GuKXA6FFR+yMmO8ksAEOLL5e574a5tLob7tt5IG+jk= after encryption but I can't decrypt on the server using a PHP function.

When I encrypt this data using the PHP function:

function encrypt($encrypt, $key=null) 
{
   $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_RAND);
   $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $encrypt, MCRYPT_MODE_ECB, $iv));
   return $encrypted;
}

I receive 6Wc3LPWvfJ7T86iG0igmdQaeZ8xs9qY419mAVWfNH+M= and I can successfully do the decryption using the following PHP function:

function decrypt($decrypt, $key=null) 
{
   $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_RAND);
   $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($decrypt), MCRYPT_MODE_ECB, $iv);
   return $decrypted;
}

With base64 encryption and decryption there are no problems; I only encounter the issue when encrypting using AES-128.

2
You probably are not using the same key on both sides. Post all of the PHP code that populates $key including declarations of the constants in the current posted code.Eric J.
A few things: 1) remove the IV, I don't know what it will do to the PHP function, but if it does anything, it will muck up the encryption/decryption 2) never use String.getBytes() without specifying the encoding to use 3) BigInteger.toByteArray() may return anything from 1 to 17 bytes, depending on the key value 4) ECB is definitely the wrong type of encryption for this. Fix those before trying anything else. I think you can safely use ASCII when communicating with PHP and using characters with code < 128.Maarten Bodewes
@Paulo: that last "Use ECB mode" is probably a typo, I think you would want to suggest CBC mode here (or any other safe scheme that provides integrity protection/authentication).Maarten Bodewes
@owlstead: Ah, thanks for the note. Horrible typo here.Paŭlo Ebermann
This will not help for your current problem, but: Do not use ECB mode, ever, until you understand why it is insecure. Use CBC mode (with a random IV transmitted together with the message), combined with some authentication (e.g. HMAC).Paŭlo Ebermann

2 Answers

1
votes

The problem isn't with the IV or the padding as I initially thought. It is with how you are handling the key in the PHP code. If you are using the actual string 4288f0b8060ca1b682bf795f2617cfdc as the key passed into mcrypt_encrypt and mcrypt_decrypt then you aren't using the same key as in the Java code. You will need to convert that hex string into bytes. You can do this in the following way:

$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, pack("H*", $key), base64_decode($decrypt), MCRYPT_MODE_ECB, $iv);

Notice the addition of pack("H*", $key) to convert the value. I found that here in the comments for the PHP bin2hex function. This will fix the current problem. You may run into padding troubles when working with data of different lengths since PHP doesn't do PKCS5 padding. See this comment about implementing that missing function. Also, I'd recommend looking into CBC instead of ECB due to ECB's unsuitability and weaknesses for data encryption.

1
votes

You can validate the output from your Java method at the command line using openssl. Java will default your IV to 0 if unspecified.

The file "enc.txt" contains "6GuKXA6FFR+yMmO8ksAEOLL5e574a5tLob7tt5IG+jk=" [corrected]

Run

openssl aes-128-ecb -in enc.txt -a -K 4288f0b8060ca1b682bf795f2617cfdc -iv 0 -d

The result is:

{"action":"getQuestion"}

Try your mcrypt_decrypt with an $iv value of 0.