9

Trying to encrypt sample data using AES128 algorithm with CBC and PKCS7 padding in Android and iOS, but results are different :(

Android code:

private static final byte[] KEY = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};

int srcBuffSiz = 1024;
byte[] srcBuff = new byte[srcBuffSiz];
Arrays.fill(srcBuff, (byte)0x01);

SecretKeySpec skeySpec = new SecretKeySpec(KEY, "AES");
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
ecipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] dstBuff = ecipher.doFinal(srcBuff);
int bytesEncrypted = dstBuff.length;

iOS Code:

    // Source buffer
    size_t srcBuffSiz = 1024;
    unsigned char* srcBuff = new unsigned char[srcBuffSiz];
    memset(srcBuff, 0x01, srcBuffSiz);

    // Destination buffer
    size_t dstBuffSiz = srcBuffSiz + 128;
    unsigned char* dstBuff = new unsigned char[dstBuffSiz];
    memset(dstBuff, 0x00, dstBuffSiz);

    unsigned char keyPtr[kCCKeySizeAES128] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};

    size_t bytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES128,
                                          NULL /* initialization vector (optional) */,
                                          srcBuff, srcBuffSiz, /* input */
                                          dstBuff, dstBuffSiz, /* output */
                                          &bytesEncrypted);

So, in both cases I'm trying to encrypt sample 1024 bytes buffer (previosly filled with 0x01 values) using predefined sample key.

First and last 6 bytes of encrypted buffer in iOS:

ED CC 64 27 A8 99 ... 0C 44 9F EC 34 FC

First and last 6 bytes of encrypted buffer in Android:

AE 65 A9 F7 7F 0E ... 1F BD AE 8B 85 ED

Any idea?

If i replace Cipher.getInstance("AES/CBC/PKCS7Padding") to Cipher.getInstance("AES"), then first several bytes of encrypted buffer will be the same, but from 17th byte ...

iOS:

ED CC 64 27 A8 99 DA 83 D5 4A B0 03 0F E7 DD A7 35 F2 50 5C 49 47 CC 3B 2F AB D1 61 05 

Android:

ED CC 64 27 A8 99 DA 83 D5 4A B0 03 0F E7 DD A7 ED CC 64 27 A8 99 DA 83 D5 4A B0 03 0F 
Tutankhamen
  • 3,532
  • 1
  • 30
  • 38
  • have u tried to decrypt the result of another phone? say, android decrypt iOS result and iOS try Android result? – dumbfingers Oct 24 '12 at 08:01
  • No, i haven't. I thought an encryption result should be the same. – Tutankhamen Oct 24 '12 at 08:05
  • unsigned char array VS a byte array.. don't you think something is different between these? :) – Anders Metnik Oct 24 '12 at 08:07
  • Anders Metnik: in that case it's doesn't matter. – Tutankhamen Oct 24 '12 at 08:13
  • Replace Cipher.getInstance("AES/CBC/PKCS7Padding") with Cipher.getInstance("AES").. See above... – Tutankhamen Oct 24 '12 at 08:18
  • 1
    You should try decrypt those result to see if they are the same. Because even you use the same key to encrypt the result can be different. That's the purpose of encryption. If everytime u use the same key get the same result, it's not collision safe. See this: http://stackoverflow.com/questions/11818684/why-is-aes-encrypted-cipher-of-the-same-string-with-the-same-key-always-differen – dumbfingers Oct 24 '12 at 08:24
  • 1
    ss1271: I don't use any salt in my code, so, the result can't different. – Tutankhamen Oct 24 '12 at 08:29
  • have a look at this answer from me http://stackoverflow.com/questions/17535918/aes-gets-different-results-in-ios-and-java/19219704#19219704 – A.S. Oct 21 '13 at 08:14
  • Why do you need the encrypted data to be equal? Probably you'll make your code less secure without reason. In most use cases only decrypted data must be equal. See crypto.stackexchange.com/q/5094 – Christian Strempfer Aug 07 '14 at 06:58

2 Answers2

10

I vaguely recall I had once similar issue of "synchronizing" the encryption between Android and iPhone, and the solution was in proper IV (initialization vector) usage. So probably switching on an explicit IV usage in Android could help:

final byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
.. // the rest of preparations
ecipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);

Because when on iPhone you pass NULL as the IV, it may internally use a default one that corresponds to the just stated above.

But in production environment you should use a (cryptographically secure pseudo-)random initialization vector, stored together with the data. Then it is safe for all modes of operations. [1]

Community
  • 1
  • 1
Vit Khudenko
  • 28,288
  • 10
  • 63
  • 91
  • 4
    Despite the header comment in CommonCryptor, IV is not "optional." The NULL IV on iOS means an all-zeros IV. (This of course dramatically reduces the security of the first 16 bytes, and in some cases more, which is why a random IV must be used here. But in any case, it is required that both use the same IV.) – Rob Napier Oct 24 '12 at 15:43
  • Thanx guys, everything is ok now! – Tutankhamen Oct 24 '12 at 23:22
  • Thank you so much for help i tried with you provided code it does not decrypt first 16 characters remaining character successfully decrypt any idea why i can't decrypt full string? thanks – Zeeshan Aug 18 '14 at 07:32
0

The Android code uses explicitly CBC mode. But the iOS code does not specify this. At least I don't see it there.

Also when you use CBC mode, you must also specify Initialization Vector:

byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; // use different random value
AlgorithmParameterSpec algorithmSpec = new IvParameterSpec(iv);
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
ecipher.init(Cipher.ENCRYPT_MODE, skeySpec, algorithmSpec);

You should use the same initialization vector on iOS and also specify you are using CBC mode.

petrsyn
  • 5,054
  • 3
  • 45
  • 48
  • thanks for you help I tried it decrypt but it does not decrypt first 16 or 19 characters any idea why? – Zeeshan Aug 18 '14 at 05:30