silentnuke
silentnuke

Reputation: 2622

Encryption using AES-128 in Java

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.

Upvotes: 2

Views: 5427

Answers (2)

laz
laz

Reputation: 28638

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.

Upvotes: 1

phatfingers
phatfingers

Reputation: 10250

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.

Upvotes: 1

Related Questions