RonoKim
RonoKim

Reputation: 184

AES128 CBC encryption in Java and Objective C giving different outputs

My java and objective c encryption methods are producing different outputs - AES128, CBC mode.

key: YnA+lracf9xaiJO1oA/bTQ==
iV: 190Dt3MNeL32o9Kd37HZlQ==
Plain text: text to encrypt

Java output: mHZpz52LOK2K76t3B/EUuA==
Obj C output: Fb0D46H4tN+ukgI05x/Dbg==

Java code:

public static String AESEncrypt(String text, String key, String iv) throws Exception {
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
     byte[] keyBytes = new byte[16];
     byte[] b = key.getBytes("UTF-8");
     int len = b.length;
     if (len > keyBytes.length)
         len = keyBytes.length;
     System.arraycopy(b, 0, keyBytes, 0, len);

     byte[] keyBytesiv = new byte[16];
     byte[] biv = iv.getBytes("UTF-8");
     int leniv = biv.length;
     if (leniv > keyBytesiv.length)
         leniv = keyBytesiv.length;
     System.arraycopy(biv, 0, keyBytes, 0, len);
     SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
     IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv);

     cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

     byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
     BASE64Encoder encoder = new BASE64Encoder();
     return encoder.encode(results);
 }

Objective C code

+ (NSData *)AESOperation:(CCOperation)operation OnData:(NSData *)data key:(NSData *)key iV:(NSData *) iv {

  NSUInteger dataLength = [data length];
  size_t bufferSize = dataLength + kCCBlockSizeAES128;
  void *buffer = malloc(bufferSize);

  size_t numBytesEncrypted = 0;
  CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                      kCCAlgorithmAES128,
                                      kCCOptionPKCS7Padding,
                                      [key bytes],
                                      kCCBlockSizeAES128,
                                      [iv bytes],
                                      [data bytes],
                                      dataLength,
                                      buffer,
                                      bufferSize,
                                      &numBytesEncrypted);
  if (cryptStatus == kCCSuccess) {
     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
  }

  free(buffer);
  return nil;
}

Upvotes: 1

Views: 843

Answers (2)

RonoKim
RonoKim

Reputation: 184

I was able to solve the issue on the java code thanks to suggestions above. Here is the Java code that worked for me to achieve AES128 CBC mode on both java and objective c

public static String AESEncrypt(String text, String key, String iv) throws Exception {

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
     byte[] keyBytes = new byte[16];
     byte[] b = new BASE64Decoder().decodeBuffer(key);
     int len = b.length;
     if (len > keyBytes.length)
         len = keyBytes.length;
     System.arraycopy(b, 0, keyBytes, 0, len);

     byte[] keyBytesiv = new byte[16];
     byte[] biv = new BASE64Decoder().decodeBuffer(iv);
     int leniv = biv.length;
     if (leniv > keyBytesiv.length)
         leniv = keyBytesiv.length;
     System.arraycopy(biv, 0, keyBytesiv, 0, len);

     SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
     IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv);

     cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

     byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
     BASE64Encoder encoder = new BASE64Encoder();
     return encoder.encode(results);
 }

Upvotes: 0

Ghislain Fourny
Ghislain Fourny

Reputation: 7279

There are two approaches to issues like this, which can be combined:

  • As a sanity check, try to decrypt the encrypted text and see if it matches the original, in both languages.

  • Try with another library (a third one) and compare to the first two values.

So I tried decrypting the ciphertext with an online tool, and could recover the original text ("text to encrypt") with the Objective C output. It shows that there is something wrong with the Java code. I suspect it may have to do with the fact that the input (key, iv) is base64-encoded, whereas it seems to be treated simply as UTF-8-encoded (getBytes() call).

Upvotes: 4

Related Questions