Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AES encryption makes different result in iOS and Android

Tags:

android

ios

aes

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 
like image 805
Tutankhamen Avatar asked Oct 24 '12 07:10

Tutankhamen


People also ask

Does Android use AES encryption?

Android offers storage encryption using the Advanced Encryption Standard (AES). And most new Android devices provide AES via Arm's version 8 processor cryptography extensions.

What is AES encryption in Android?

The AES algorithm is a symmetric block cipher that can encrypt (encipher) and decrypt (decipher) information. It uses only one secret key to encrypt plain data, and uses 128-, 192-, and 256-bit keys to process 128-bit data locks. This algorithm receives data and encrypts it using a password.

What is AES in iOS?

A container for Advanced Encryption Standard (AES) ciphers. iOS 13.0+ iPadOS 13.0+ macOS 10.15+ Mac Catalyst 13.0+ tvOS 13.0+ watchOS 6.0+

Which mode of AES is more secure?

Out of 128-bit, 192-bit, and 256-bit AES encryption, 256-bit AES encryption is technically the most secure because of its key length size. Some go as far as to label 256-bit AES encryption overkill because it, based on some estimations, would take trillions of years to crack using a brute-force attack.


1 Answers

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]

like image 113
Vit Khudenko Avatar answered Oct 28 '22 11:10

Vit Khudenko