Powered By Blogger

Thursday, April 26, 2012

AES Encryption and Decryption

Hello friends,
I'm going to share AES Encryption and Decryption Method for Securely sending your data over the web. Please check the below code :


Step 1: First you have to include these two files into your project.

#include <CommonCrypto/CommonCryptor.h>

@interface NSData(AES)
- (NSData*)AES128Decrypt;
- (NSData*)AES128Encrypt;
@end


#import "NSData+AES.h"

NSString *iv = @"fedcba9876543210";
NSString *key = @"0123456789abcdef";

@implementation NSData (AES)

-(NSData*)AES128Encrypt
{
    char ivPtr[kCCKeySizeAES128 + 1];
    bzero(ivPtr, sizeof(ivPtr));
   
    // fetch iv data
    [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
   
   
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES128 + 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, 0,
                                          keyPtr, kCCKeySizeAES128,
                                           ivPtr/* 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*)AES128Decrypt
{
    char ivPtr[kCCKeySizeAES128 + 1];
    bzero(ivPtr, sizeof(ivPtr));
   
    // fetch iv data
    [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
   
   

    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES128 + 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, 0,
                                          keyPtr, kCCKeySizeAES128,
                                          ivPtr /* 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 dataWithBytes:buffer length:numBytesDecrypted] ;
    }
   
    free(buffer); //free the buffer;
    return nil;
}

@end

Step 2: You have to import "Security.framework" into your project.

Step 3: Now, you need to put below code into the class where you want to Encrypt or Decrypt a string and also need to import "NSData+AES.h" file.

- (void)testActuallyEncrypting:(NSString *)hexString
{
    NSLog(@"Encrypted HexString : %@",hexString);

    NSData *data = [self dataFromHexString:hexString];
    NSData *encryptedData =  [NSData dataWithBytes:[data bytes] length:[data length]];
    NSData *decryptedData = [encryptedData AES128Decrypt];
    NSString *decryptedString = [NSString stringWithUTF8String:[decryptedData bytes]];
    NSLog(@"Decrypted String : %@",decryptedString);

    decryptedString = [self addPaddingToString:decryptedString];
    decryptedData = [NSData dataWithBytes:[decryptedString UTF8String] length:[[decryptedString dataUsingEncoding:NSUTF8StringEncoding] length]];
    encryptedData = [decryptedData AES128Encrypt];
    if (encryptedData!=nil)
    {
        NSString *encryptedHexString = [self hexStringFromData:encryptedData];
        NSLog(@"Encrypted HexString : %@",encryptedHexString);

//        NSData *data1 = [self dataFromHexString:encryptedHexString];
//        NSData *encryptedData1 =  [NSData dataWithBytes:[data1 bytes] length:[data1 length]];
//        NSData *decryptedData1 = [encryptedData1 AES128Decrypt];
//        NSString *decryptedString1 = [NSString stringWithUTF8String:[decryptedData1 bytes]];
//        NSLog(@"Decrypted String Testing 123: %@",[decryptedString1 stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" "]]);
    }
}

Step 4 : For step3 , you have to add these three methods into your code.

// For Converting incoming HexString into NSData
- (NSData *)dataFromHexString:(NSString *)string
{  
    NSMutableData *stringData = [[[NSMutableData alloc] init] autorelease];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    int i;
    for (i=0; i < [string length] / 2; i++) {
        byte_chars[0] = [string characterAtIndex:i*2];
        byte_chars[1] = [string characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [stringData appendBytes:&whole_byte length:1];
    }
    return stringData;
}


// For converting Encrypted Data into NSString after the encryption
- (NSString*)hexStringFromData:(NSData *)data
{
    unichar* hexChars = (unichar*)malloc(sizeof(unichar) * (data.length*2));
    unsigned char* bytes = (unsigned char*)data.bytes;
    for (NSUInteger i = 0; i < data.length; i++) {
        unichar c = bytes[i] / 16;
        if (c < 10) c += '0';
        else c += 'a' - 10;
        hexChars[i*2] = c;
        c = bytes[i] % 16;
        if (c < 10) c += '0';
        else c += 'a' - 10;
        hexChars[i*2+1] = c;
    }
    NSString* retVal = [[NSString alloc] initWithCharactersNoCopy:hexChars
                                                           length:data.length*2
                                                     freeWhenDone:YES];
    return [retVal autorelease];
}
// For padding into a string for required string length
-(NSString *)addPaddingToString:(NSString *)string
{
    NSInteger size = 16;
    NSInteger x = [string length]%size;
    NSInteger padLength = size - x;
    for (int i=0; i<padLength; i++)
    {
        string = [string stringByAppendingString:@" "];
    }
    return string;
}

 By following  all above steps, you will be able to Implement AES Encryption and Decryption. If any one has query then place you it over here.

Thanks and Regards,
Nilesh Prajapati

23 comments:

  1. hi,
    I am getting following warnings:

    1) Instance method '-length' not found (return type defaults to 'id') for
    NSUInteger dataLength = [self length];

    2) Instance method '-bytes' not found (return type defaults to 'id') for

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

    I get Above warnings for both
    -(NSData*)AES128Encrypt
    - (NSData*)AES128Decrypt
    methods..
    Kindly help..

    ReplyDelete
    Replies
    1. Ok let me clear first ...
      this above code is regarding NSData . So, first you have to convert your string/any content to NSData and then you can use this files in your current code. Don't use these two methods directly to any format instance variable.

      Delete
    2. this method are belongs to NSData category , So [self length] is Data lenght.
      And Another one is [self bytes] means data converting into const char * ..
      so you can give the Nsdata to the Method or Give the Data length and bytes.

      Delete
    3. Hi,
      First of all , have you made two files "NSData+AES.h" and "NSData+AES.m"?
      Did you #import "NSData+AES.h" file into your controller file where you want to use Encryption or Decryption?

      I request you to follow all steps once again and then check what you still needed.

      Thanks

      Delete
  2. how much file size will this support to encrypt and decrypt?

    ReplyDelete
    Replies
    1. File means ? this code is for encrypt and decrypt the string value for sending data securely...

      Delete
  3. i am having a error on No visible @interface for 'NSData' declares the selector 'dataFromHexstring'...How to solve it?

    ReplyDelete
    Replies
    1. Follow the above steps one by one and one more things some times you need to use your own logical changes to make it works.

      Delete
  4. For 256 how i will do it?

    ReplyDelete
    Replies
    1. Hi,
      Yes you can go with 256 but you need to change some parameters as per 256 requirement. Please read this line in upper blog content "// 'key' should be 32 bytes for AES256, will be null-padded otherwise".

      Delete
  5. Would you have a copy of the source code for this project?

    ReplyDelete
  6. Hi,

    I am calling - (void)testActuallyEncrypting:(NSString *)hexString method from our code
    i.e. [self testActuallyEncrypting:@"39590hajdashgdadgagdadga"];
    and App get crash what worng with me?

    crash log:
    Encrypted HexString : 39590hajdashgdadgagdadga
    2013-11-01 13:52:55.489 MyLiftApp[1647:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSString stringWithUTF8String:]: NULL cString'
    *** First throw call stack:
    (
    0 CoreFoundation 0x03ed65e4 __exceptionPreprocess + 180
    1 libobjc.A.dylib 0x033f78b6 objc_exception_throw + 44
    2 CoreFoundation 0x03ed63bb +[NSException raise:format:] + 139
    3 Foundation 0x02aa28a2 +[NSString stringWithUTF8String:] + 90
    4 MyLiftApp 0x00101ff8 -[HomeScreenVC testActuallyEncrypting:] + 344
    5 MyLiftApp 0x00102860 -[HomeScreenVC viewDidLoad] + 208
    6 UIKit 0x01d0f9a8 -[UIViewController loadViewIfRequired] + 696
    7 UIKit 0x01d0fc44 -[UIViewController view] + 35
    8 MyLiftApp 0x000df2e4 -[MenuVC viewDidLoad] + 1844
    9 UIKit 0x01d0f9a8 -[UIViewController loadViewIfRequired] + 696
    10 UIKit 0x01d0fc44 -[UIViewController view] + 35
    11 UIKit 0x01d3a339 -[UINavigationController rotatingSnapshotViewForWindow:] + 52
    12 UIKit 0x02063910 -[UIClientRotationContext initWithClient:toOrientation:duration:andWindow:] + 420
    13 UIKit 0x01c3fea2 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 1495
    14 UIKit 0x01c3f8c6 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 82
    15 UIKit 0x01c3f798 -[UIWindow

    ReplyDelete
  7. Hello,
    sorry for delay but some thing going wrong within these two lines ...

    NSData *decryptedData = [encryptedData AES128Decrypt];
    NSString *decryptedString = [NSString stringWithUTF8String:[decryptedData bytes]];

    Your code might not able to decrypt your encrypted string.

    Thanks

    ReplyDelete
  8. Hi, i tried your blog, the following lines is not working fine for converting decrypted dataq to decrypted string,

    NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSASCIIStringEncoding];

    NSString* newStr = [NSString stringWithUTF8String:[decryptedData bytes]];

    NSLog(@"decryptedData String : %@",decryptedData);

    NSLog(@"newStr String : %@",newStr);. Decrypted data goes null, how to clear it, please clear me

    ReplyDelete
    Replies
    1. Hello,
      Sorry but please read blog first and then follow the steps which are mentioned over here. One more thing is about below values..
      NSString *iv = @"fedcba9876543210";
      NSString *key = @"0123456789abcdef";

      I already tried posted code into my one of the project. I used this concept in my one of the project to make it private.

      Regards,
      Nilesh Prajapati

      Delete
  9. 'Foundation/NSRaise.h' file not found. Receiving this error, please help.

    ReplyDelete
    Replies
    1. Hi,
      Check for Foundation.framework in your project first and then try below one ..
      https://github.com/AriX/FrozenCocoa-POC/blob/master/jni%20w:%20itoa%20runtime%20and%20allocator/Foundation/NSRaise.h

      Delete
  10. can you give me full souce code for encrypt and decrypt String
    Emaild id:hiteshborse12@gmail.com

    ReplyDelete
  11. I followed all the steps of the post, but does not work.
    The method - (NSData *) AES128Decrypt I always returns a null value.
    I did debug, and I noticed that when I plug in the block parameter [self bytes], always has the value nil and so the method I always returns 0.
    Where am I wrong?

    ReplyDelete
  12. can you give me full souce code for encrypt and decrypt String
    Emaild id:veeranji29@gmail.com

    ReplyDelete
  13. Unknown class ViewController in Interface Builder file

    error what i missing plz reply asap

    ReplyDelete
  14. can you give me full souce code for encrypt and decrypt String
    Emails id:puja.rathod@rawalinfocom.com

    ReplyDelete
  15. Hi,

    I am calling - (void)testActuallyEncrypting:(NSString *)hexString method from our code
    i.e. [self testActuallyEncrypting:@"39590hajdashgdadgagdadga"];
    and App get crash what worng with me?

    crash log:
    Encrypted HexString : 39590hajdashgdadgagdadga
    2013-11-01 13:52:55.489 MyLiftApp[1647:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSString stringWithUTF8String:]: NULL cString'
    *** First throw call stack:
    (
    0 CoreFoundation 0x03ed65e4 __exceptionPreprocess + 180
    1 libobjc.A.dylib 0x033f78b6 objc_exception_throw + 44
    2 CoreFoundation 0x03ed63bb +[NSException raise:format:] + 139
    3 Foundation 0x02aa28a2 +[NSString stringWithUTF8String:] + 90
    4 MyLiftApp 0x00101ff8 -[HomeScreenVC testActuallyEncrypting:] + 344
    5 MyLiftApp 0x00102860 -[HomeScreenVC viewDidLoad] + 208
    6 UIKit 0x01d0f9a8 -[UIViewController loadViewIfRequired] + 696
    7 UIKit 0x01d0fc44 -[UIViewController view] + 35
    8 MyLiftApp 0x000df2e4 -[MenuVC viewDidLoad] + 1844
    9 UIKit 0x01d0f9a8 -[UIViewController loadViewIfRequired] + 696
    10 UIKit 0x01d0fc44 -[UIViewController view] + 35
    11 UIKit 0x01d3a339 -[UINavigationController rotatingSnapshotViewForWindow:] + 52
    12 UIKit 0x02063910 -[UIClientRotationContext initWithClient:toOrientation:duration:andWindow:] + 420
    13 UIKit 0x01c3fea2 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 1495
    14 UIKit 0x01c3f8c6 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 82
    15 UIKit 0x01c3f798 -[UIWindow

    ReplyDelete