Any cocoa source code for AES encryption decryption?

24,901

Solution 1

AES128 encryption is available on the iPhone in the CommonCrypto framework. The relevant functions are in the CommonCryptor.h header.

You can create a cryptor like so:

// Assume key and keylength exist
CCCryptorRef cryptor;
if(kCCSuccess != CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES128, 0, key, keyLength, NULL, &cryptor))
  ; //handle error

// Repeatedly call CCCryptorUpdate to encrypt the data

CCCryptorRelease(cryptor);

It seems from the question and the link that you are looking for example implementations of AES. I would not recommend this- use Apple's implementation!

It looks like http://pastie.org/297563.txt might help you also, but I haven't tested it.

Solution 2

I use a simple category on NSData that uses the built-in CommonCrypto framework to do AES 256-bit encryption. I use this on the Mac but it should work OK on iPhone too:

#import <CommonCrypto/CommonCryptor.h>
@implementation NSData (AESAdditions)
- (NSData*)AES256EncryptWithKey:(NSString*)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize           = dataLength + kCCBlockSizeAES128;
    void* buffer                = malloc(bufferSize);

    size_t numBytesEncrypted    = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesEncrypted);

    if (cryptStatus == kCCSuccess)
    {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

- (NSData*)AES256DecryptWithKey:(NSString*)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize           = dataLength + kCCBlockSizeAES128;
    void* buffer                = malloc(bufferSize);

    size_t numBytesDecrypted    = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesDecrypted);

    if (cryptStatus == kCCSuccess)
    {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}
@end

Solution 3

All examples I found didn't work for me, so I changed the solution above. This one works for me and uses the Google-Lib for Base64 stuff:

+ (NSData *)AES256DecryptWithKey:(NSString *)key data:(NSData*)data encryptOrDecrypt:(CCOperation)encryptOrDecrypt {

    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    if (encryptOrDecrypt == kCCDecrypt)
    {
        data = [GTMBase64 decodeData:data];
    }

        NSUInteger dataLength = [data length];

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;

    void *buffer = malloc(bufferSize);

    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(encryptOrDecrypt,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding,
                                          keyPtr,
                                          kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [data bytes], dataLength, /* input */
                                          buffer,       bufferSize, /* output */
                                          &numBytesDecrypted);

    if (cryptStatus != kCCSuccess){ 
        NSLog(@"ERROR WITH FILE ENCRYPTION / DECRYPTION");
        return nil;
    }

    NSData *result;

    if (encryptOrDecrypt == kCCDecrypt)
    {
        result = [NSData dataWithBytes:(const void *)buffer length:(NSUInteger)numBytesDecrypted];
    }
    else
    {
        NSData *myData = [NSData dataWithBytes:(const void *)buffer length:(NSUInteger)numBytesDecrypted];
        result = [GTMBase64 encodeData:myData];
    }

    free(buffer); //free the buffer;
    return result;
}

Solution 4

thanks for the great category extension. One thing that I've discovered - when you use CCCrypt with an algorithm stronger then 64 bit, you need to be compliant to the BIS export regulations. See the iTunes Connect FAQ for more details. Even if you use Apple's inbuild crypto api you need to get approval from the BIS.

There was a discussion on sf about this topic before (in context of ssl usage):

Using SSL in an iPhone App - Export Compliance

Best Regards Chris

Share:
24,901
Devarshi
Author by

Devarshi

A developer in love with programming :) My LinkedIn profile - Devarshi Kulshreshtha

Updated on May 16, 2020

Comments

  • Devarshi
    Devarshi almost 4 years

    I am searching for some cocoa code on AES encryption and I did some google search for it. I found this very useful link - http://iphonedevelopment.blogspot.com/2009/02/strong-encryption-for-cocoa-cocoa-touch.html. So I tried it but it did not work for me.

    Can anyone suggest me some useful link or source code which can help me to implement it in my sample application.

    • Nico
      Nico over 14 years
      Whatever you end up using, it'd be a good idea to put it (if it isn't already) in a couple of methods to encrypt and decrypt, then create a test case that attempts to encrypt and decrypt a sample string using these methods just as your app does. If the sample comes out the other end comparing equal to the original sample, you know it's working. If it doesn't, you know it's broken. (While you're at it, also test that the encrypted text does not compare equal to, or even contain as a substring, the cleartext. You really don't want that to be broken.)
    • Imdad
      Imdad almost 11 years
      I think you should use OpenSSL encryption. its quite good see this deusty.blogspot.in/2007/01/using-openssl-in-cocoa.html
  • Devarshi
    Devarshi over 14 years
    Thanks sbooth [pastie.org/297563.txt][1] is working Is there any source for base 128 encoding/decoding??
  • Devarshi
    Devarshi over 14 years
    irsk, thanks for your reply! However we are facing same problem in your code which we were facing with previous code!!
  • Admin
    Admin almost 13 years
    Hey, I use NSBundle + pathForResource for filepath and choosing a file to encrypt, but how do I connect it to the actual encryption. I know this is a stupid question, but how do you call the encrypt and decrypt NSData methods to use on a button? Like [self whatever], but I can't find the input for 'key' Thanks!
  • Rob Napier
    Rob Napier over 12 years
    Note that the paste provided has a hard-coded key from a restricted keyspace (which is to say it's much easier to guess than a full keyspace key), and uses no IV, so it's vulnerable to replay attacks. For simple usage, it looks pretty well written, but not for something that was actually going to be attacked.
  • Rob Napier
    Rob Napier over 12 years
    I've encountered this block of code a lot and it has a number of security problems. I've written them up with some replacement code here: robnapier.net/blog/aes-commoncrypto-564.