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
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:
You should use the same initialization vector on iOS and also specify you are using CBC mode.
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:
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]