2

I have an iOS mobile app that encrypts data and stores it in files in the app sandbox. Files are encrypted using CCCrypt() as follows:

    CCCryptorStatus aCryptStatus = CCCrypt(kCCEncrypt, 
                                       kCCAlgorithmAES128, 
                                       kCCOptionPKCS7Padding,
                                       aKeyPtr, 
                                       kCCKeySizeAES256,
                                       aIVPtr,
                                       [self bytes], 
                                       aDataLength, 
                                       aBuffer, 
                                       aBufferSize, 
                                       &aNumBytesEncrypted);

The key is 256 bits long, the IV is 128 bits long. I'm a not an expert with encryption, but this should be using CBC mode (default for CCCrypt()) and it is my understanding that the PKCS#7 padding option specified here is equivalent to openssl's PKCS#5 padding.

The data is written to a file as follows:

     NSData* aSerializedData = [[self serialize]  dataUsingEncoding:NSUTF8StringEncoding];
     NSData* aEncryptedData = [aSerializedData AES256EncryptWithKey:ENCKey 
                                               InitializationVector:ENCIv]; 
     NSFileManager* aFileManager = [[NSFileManager alloc] init];
     BOOL aFileWritten = [aFileManager createFileAtPath:aFilePath 
                                               contents:aEncryptedData 
                                             attributes:nil];

I have attempted to decrypt the file using openssl as follows (key and iv replaced with 0's):

$ openssl enc -aes-128-cbc -d -K 00000000000000000000000000000000 -iv 0000000000000000 -in encrypted.dat -out decrypted.txt 

and

$ openssl enc -aes-256-cbc -d -K 00000000000000000000000000000000 -iv 0000000000000000 -in encrypted.dat -out decrypted.txt 

Both return the same error:

bad decrypt 28969:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:/SourceCache/OpenSSL098/OpenSSL098-50/src/crypto/evp/evp_enc.c:330:

I've also tried other modes and other options such as -nosalt and -a. None have returned the cleartext.

I've spent hours trying to find an example of how to do this anywhere online, but nothing that has helped me resolve the problem. Help would be appreciated.

==========

Answer: The key in CCCrypt is a 32 char string that gets converted to 256 bits. The key expected by openssl is the 64 hex digits from the binary representation of that string. Similarly, the iv in CCCrypt is a 16 char string that gets converted into 128 bits. The iv expected by openssl is the hex representation of that string. Once I used the hex representations of those two, it decrypted easily.

Chuck Krutsinger
  • 2,830
  • 4
  • 28
  • 50

1 Answers1

4

The openssl key and iv as specified with -K and -iv are specified as a hex representation of the binary data.
From the openssl docs:

the actual key to use: this must be represented as a string comprised only of hex digits.

Both of the openssl keys in the example are 128 bits, for AES 256 they need to be 256 bits. The iv must be block size, 128 bits but in the above example the iv is only 64 bits.

I tested and this works:

uint8_t *zeros     = calloc(1, 256);
NSData  *keyData   = [NSData dataWithBytes:zeros length:16];
NSData  *ivData    = [NSData dataWithBytes:zeros length:16];
NSData  *clearData = [@"0123456789abcdef" dataUsingEncoding:NSUTF8StringEncoding];

NSData *encryptedData = [AESTest doCipher:clearData iv:ivData key:keyData context:kCCEncrypt error:&error];
[encryptedData writeToFile:@"/Users/dan/Desktop/encrypted.dat" atomically:YES];

openssl enc -aes-128-cbc -d -K 00000000000000000000000000000000 -iv 00000000000000000000000000000000 -in /Users/dan/Desktop/encrypted.dat -out /Users/dan/Desktop/decrypted.txt

cat /Users/dan/Desktop/decrypted.txt
0123456789abcdef

For the method doCipher see this SO answer

Community
  • 1
  • 1
zaph
  • 111,848
  • 21
  • 189
  • 228
  • How are you counting bits? The key in the example I gave is 32 bytes (x 8 bits/byte = 256) just as yours is, and the iv in the example is 16 bytes (x 8 bits/byte = 128 bits). – Chuck Krutsinger May 15 '14 at 13:55
  • OpenSSL states that the input is in hex characters, each hex character represents four bits. Hex characters are 0-9a-f, that is 16 characters which can only represent 4 bits. Note that the key I am using is for AES128, not AES256 (openssl enc -aes-128-cbc). – zaph May 15 '14 at 14:00
  • You are correct. I was confusing the key in ASCII with the key in hex. When I captured the correct key, I was able to decrypt with openssl. Thanks! – Chuck Krutsinger May 15 '14 at 14:53