Search code examples
iosaescommoncrypto

CCCrypt decrypting in AES


In my iOS app I have to decrypt data coming from a server. I use CommonCrypto framework and, after several trials, I successfully decrypted with

CCCrypt(kCCDecrypt, // operation
                     kCCAlgorithmAES128, // Algorithm
                     kCCOptionPKCS7Padding | kCCModeCBC, // options
                     key.bytes, // key
                     key.length, // keylength
                     nil,// iv
                     cipherData.bytes, // dataIn
                     cipherData.length, // dataInLength,
                     decryptedData.mutableBytes, // dataOut
                     decryptedData.length, // dataOutAvailable
                     &outLength); // dataOutMoved

In the java server the data is crypted with

byte[] buff = new byte[100];
byte[] buf2 = new byte[32];
byte[] mainKey = ...
byte[] raw = ...
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new AESEngine());
KeyParameter par = new KeyParameter(mainKey);
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 + length2;
byte[] result = new byte[actualLength];
System.arraycopy(outBuf, 0, result, 0, result.length);

Now, I don't understand the sense of kCCOptionPKCS7Padding | kCCModeCBC. kCCOptionPKCS7Padding = 0x0001 and kCCModeCBC = 2 so kCCOptionPKCS7Padding | kCCModeCBC = 3 but not exist options for block ciphers with value 3.

Is there someone that can help me to understand?


Solution

  • Your use of kCCModeCBC here is incorrect. All CCOption enum values begin with kCCOption. kCCModeCBC is part of the CCMode enum. You can't combine them this way. You're getting away with it because CBC happens to be the default. You should remove | kCCModeCBC. (CCMode is used by a newer interface called CCCryptorCreateWithMode. The interface you're using defaults to CBC and has an option to switch to ECB mode instead.))

    To your deeper question, these are bit fields. So "bit zero" (which has a value of 1) is PKCS7 padding. Bit one (which has a value of 2) turns on ECB (not CBC). If you "or" them (which this the same as adding them), you get 3, which means both options. This is an extremely common way to pass boolean data in C, giving each field one bit in a larger integer.

    If there were more fields, they would have values 4, 8, 16, 32, etc. All powers of two. So the options you turn on or off are exactly a binary number of ones (on) and zeros (off).

    C does not have a really good way to maintain type safety for these kinds of values, so it won't stop you from combining unrelated enums like you've done here.


    The reason it "works" with kCCModeCBC is that it has the same value as kCCOptionECBMode. Your encryption is in ECB mode, not CBC mode. (Which happens to mean that your cypher is almost certainly deeply insecure, but that's a separate issue.)