RSA implementations in Objective C RSA implementations in Objective C ios ios

RSA implementations in Objective C


I have tried RSA Encryption and Decryption for NSString. Here is the code:

Add Security.Framework to your project bundle.

ViewController.h code is as follows:

#import <UIKit/UIKit.h>#import <Security/Security.h>@interface ViewController : UIViewController{SecKeyRef publicKey;SecKeyRef privateKey;    NSData *publicTag;    NSData *privateTag;}- (void)encryptWithPublicKey:(uint8_t *)plainBuffer cipherBuffer:(uint8_t *)cipherBuffer;- (void)decryptWithPrivateKey:(uint8_t *)cipherBuffer plainBuffer:(uint8_t *)plainBuffer;- (SecKeyRef)getPublicKeyRef;- (SecKeyRef)getPrivateKeyRef;- (void)testAsymmetricEncryptionAndDecryption;- (void)generateKeyPair:(NSUInteger)keySize;@end

ViewController.m file code is as follows:

#import "ViewController.h"const size_t BUFFER_SIZE = 64;const size_t CIPHER_BUFFER_SIZE = 1024;const uint32_t PADDING = kSecPaddingNone;static const UInt8 publicKeyIdentifier[] = "com.apple.sample.publickey";static const UInt8 privateKeyIdentifier[] = "com.apple.sample.privatekey";@implementation ViewController-(SecKeyRef)getPublicKeyRef {     OSStatus sanityCheck = noErr;     SecKeyRef publicKeyReference = NULL;    if (publicKeyReference == NULL) {         [self generateKeyPair:512];                NSMutableDictionary *queryPublicKey = [[NSMutableDictionary alloc] init];        // Set the public key query dictionary.        [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];        [queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];        [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];        [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];        // Get the key.        sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKeyReference);        if (sanityCheck != noErr)        {            publicKeyReference = NULL;        }//        [queryPublicKey release];    } else { publicKeyReference = publicKey; }    return publicKeyReference; }- (void)didReceiveMemoryWarning{    [super didReceiveMemoryWarning];    // Release any cached data, images, etc that aren't in use.}- (void)testAsymmetricEncryptionAndDecryption {    uint8_t *plainBuffer;    uint8_t *cipherBuffer;    uint8_t *decryptedBuffer;    const char inputString[] = "This is a test demo for RSA Implementation in Objective C";    int len = strlen(inputString);    // TODO: this is a hack since i know inputString length will be less than BUFFER_SIZE    if (len > BUFFER_SIZE) len = BUFFER_SIZE-1;    plainBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t));    cipherBuffer = (uint8_t *)calloc(CIPHER_BUFFER_SIZE, sizeof(uint8_t));    decryptedBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t));    strncpy( (char *)plainBuffer, inputString, len);    NSLog(@"init() plainBuffer: %s", plainBuffer);    //NSLog(@"init(): sizeof(plainBuffer): %d", sizeof(plainBuffer));    [self encryptWithPublicKey:(UInt8 *)plainBuffer cipherBuffer:cipherBuffer];    NSLog(@"encrypted data: %s", cipherBuffer);    //NSLog(@"init(): sizeof(cipherBuffer): %d", sizeof(cipherBuffer));    [self decryptWithPrivateKey:cipherBuffer plainBuffer:decryptedBuffer];    NSLog(@"decrypted data: %s", decryptedBuffer);    //NSLog(@"init(): sizeof(decryptedBuffer): %d", sizeof(decryptedBuffer));    NSLog(@"====== /second test =======================================");    free(plainBuffer);    free(cipherBuffer);    free(decryptedBuffer);}/* Borrowed from: * https://developer.apple.com/library/mac/#documentation/security/conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html */- (void)encryptWithPublicKey:(uint8_t *)plainBuffer cipherBuffer:(uint8_t *)cipherBuffer{    NSLog(@"== encryptWithPublicKey()");    OSStatus status = noErr;    NSLog(@"** original plain text 0: %s", plainBuffer);    size_t plainBufferSize = strlen((char *)plainBuffer);    size_t cipherBufferSize = CIPHER_BUFFER_SIZE;    NSLog(@"SecKeyGetBlockSize() public = %lu", SecKeyGetBlockSize([self getPublicKeyRef]));    //  Error handling    // Encrypt using the public.    status = SecKeyEncrypt([self getPublicKeyRef],                           PADDING,                           plainBuffer,                           plainBufferSize,                           &cipherBuffer[0],                           &cipherBufferSize                           );    NSLog(@"encryption result code: %ld (size: %lu)", status, cipherBufferSize);    NSLog(@"encrypted text: %s", cipherBuffer);}- (void)decryptWithPrivateKey:(uint8_t *)cipherBuffer plainBuffer:(uint8_t *)plainBuffer{    OSStatus status = noErr;    size_t cipherBufferSize = strlen((char *)cipherBuffer);    NSLog(@"decryptWithPrivateKey: length of buffer: %lu", BUFFER_SIZE);    NSLog(@"decryptWithPrivateKey: length of input: %lu", cipherBufferSize);    // DECRYPTION    size_t plainBufferSize = BUFFER_SIZE;    //  Error handling    status = SecKeyDecrypt([self getPrivateKeyRef],                           PADDING,                           &cipherBuffer[0],                           cipherBufferSize,                           &plainBuffer[0],                           &plainBufferSize                           );    NSLog(@"decryption result code: %ld (size: %lu)", status, plainBufferSize);    NSLog(@"FINAL decrypted text: %s", plainBuffer);}- (SecKeyRef)getPrivateKeyRef {    OSStatus resultCode = noErr;    SecKeyRef privateKeyReference = NULL;//    NSData *privateTag = [NSData dataWithBytes:@"ABCD" length:strlen((const char *)@"ABCD")];//    if(privateKey == NULL) {        [self generateKeyPair:512];        NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init];        // Set the private key query dictionary.        [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];        [queryPrivateKey setObject:privateTag forKey:(__bridge id)kSecAttrApplicationTag];        [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];        [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];        // Get the key.        resultCode = SecItemCopyMatching((__bridge CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKeyReference);        NSLog(@"getPrivateKey: result code: %ld", resultCode);        if(resultCode != noErr)        {            privateKeyReference = NULL;        }//        [queryPrivateKey release];//    } else {//        privateKeyReference = privateKey;//    }    return privateKeyReference;}#pragma mark - View lifecycle- (void)viewDidLoad{    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.}- (void)viewDidUnload{    [super viewDidUnload];    // Release any retained subviews of the main view.    // e.g. self.myOutlet = nil;}- (void)viewWillAppear:(BOOL)animated{    [super viewWillAppear:animated];    privateTag = [[NSData alloc] initWithBytes:privateKeyIdentifier length:sizeof(privateKeyIdentifier)];    publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];    [self testAsymmetricEncryptionAndDecryption];}- (void)viewDidAppear:(BOOL)animated{    [super viewDidAppear:animated];}- (void)viewWillDisappear:(BOOL)animated{    [super viewWillDisappear:animated];}- (void)viewDidDisappear:(BOOL)animated{    [super viewDidDisappear:animated];}- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{    // Return YES for supported orientations    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {        return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);    } else {        return YES;    }}- (void)generateKeyPair:(NSUInteger)keySize {    OSStatus sanityCheck = noErr;    publicKey = NULL;    privateKey = NULL;//  LOGGING_FACILITY1( keySize == 512 || keySize == 1024 || keySize == 2048, @"%d is an invalid and unsupported key size.", keySize );    // First delete current keys.//  [self deleteAsymmetricKeys];    // Container dictionaries.    NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init];    NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init];    NSMutableDictionary * keyPairAttr = [[NSMutableDictionary alloc] init];    // Set top level dictionary for the keypair.    [keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];    [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits];    // Set the private key dictionary.    [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];    [privateKeyAttr setObject:privateTag forKey:(__bridge id)kSecAttrApplicationTag];    // See SecKey.h to set other flag values.    // Set the public key dictionary.    [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];    [publicKeyAttr setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];    // See SecKey.h to set other flag values.    // Set attributes to top level dictionary.    [keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];    [keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];    // SecKeyGeneratePair returns the SecKeyRefs just for educational purposes.    sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKey, &privateKey);//  LOGGING_FACILITY( sanityCheck == noErr && publicKey != NULL && privateKey != NULL, @"Something really bad went wrong with generating the key pair." );    if(sanityCheck == noErr  && publicKey != NULL && privateKey != NULL)    {        NSLog(@"Successful");    }//  [privateKeyAttr release];//  [publicKeyAttr release];//  [keyPairAttr release];}@end

Here is where I originally posted my answer : Iphone - How to encrypt NSData with public key and decrypt with private key?

Let me know if you need more help.

Hope this helps.


It's very cool!However i think it should not be a subclass of a UIViewController, but an NSObject, i changed and it works for me, here it is:

NOTE: ALL WORK IS THANKED TO @Parth Bath

RSAManager.h

@interface RSAManager : NSObject{   SecKeyRef publicKey;   SecKeyRef privateKey;   NSData *publicTag;   NSData *privateTag;}- (void)encryptWithPublicKey:(uint8_t *)plainBuffer cipherBuffer:(uint8_t *)cipherBuffer;- (void)decryptWithPrivateKey:(uint8_t *)cipherBuffer plainBuffer:(uint8_t *)plainBuffer;- (SecKeyRef)getPublicKeyRef;- (SecKeyRef)getPrivateKeyRef;- (void)testAsymmetricEncryptionAndDecryption;- (void)generateKeyPair:(NSUInteger)keySize;@end

RSAManager.m

#import "RSAManager.h"const size_t BUFFER_SIZE = 64;const size_t CIPHER_BUFFER_SIZE = 1024;const uint32_t PADDING = kSecPaddingNone;static const UInt8 publicKeyIdentifier[] = "com.apple.sample.publickey";static const UInt8 privateKeyIdentifier[] = "com.apple.sample.privatekey";@implementation RSAManager- (id)init{   self = [super init];   if(self) {      privateTag = [[NSData alloc] initWithBytes:privateKeyIdentifier length:sizeof(privateKeyIdentifier)];      publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];      [self testAsymmetricEncryptionAndDecryption];   }   return self;}-(SecKeyRef)getPublicKeyRef {   OSStatus sanityCheck = noErr;   SecKeyRef publicKeyReference = NULL;   if (publicKeyReference == NULL) {      [self generateKeyPair:512];      NSMutableDictionary *queryPublicKey = [[NSMutableDictionary alloc] init];      // Set the public key query dictionary.      [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];      [queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];      [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];      [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];      // Get the key.      sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKeyReference);      if (sanityCheck != noErr)      {         publicKeyReference = NULL;      }      //        [queryPublicKey release];   } else { publicKeyReference = publicKey; }   return publicKeyReference;}- (void)testAsymmetricEncryptionAndDecryption {   uint8_t *plainBuffer;   uint8_t *cipherBuffer;   uint8_t *decryptedBuffer;   const char inputString[] = "This is a test demo for RSA Implementation in Objective C";   int len = strlen(inputString);   // TODO: this is a hack since i know inputString length will be less than BUFFER_SIZE   if (len > BUFFER_SIZE) len = BUFFER_SIZE-1;   plainBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t));   cipherBuffer = (uint8_t *)calloc(CIPHER_BUFFER_SIZE, sizeof(uint8_t));   decryptedBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t));   strncpy( (char *)plainBuffer, inputString, len);   NSLog(@"init() plainBuffer: %s", plainBuffer);   //NSLog(@"init(): sizeof(plainBuffer): %d", sizeof(plainBuffer));   [self encryptWithPublicKey:(UInt8 *)plainBuffer cipherBuffer:cipherBuffer];   NSLog(@"encrypted data: %s", cipherBuffer);   //NSLog(@"init(): sizeof(cipherBuffer): %d", sizeof(cipherBuffer));   [self decryptWithPrivateKey:cipherBuffer plainBuffer:decryptedBuffer];   NSLog(@"decrypted data: %s", decryptedBuffer);   //NSLog(@"init(): sizeof(decryptedBuffer): %d", sizeof(decryptedBuffer));   NSLog(@"====== /second test =======================================");   free(plainBuffer);   free(cipherBuffer);   free(decryptedBuffer);}/* Borrowed from: * https://developer.apple.com/library/mac/#documentation/security/conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html */- (void)encryptWithPublicKey:(uint8_t *)plainBuffer cipherBuffer:(uint8_t *)cipherBuffer{   NSLog(@"== encryptWithPublicKey()");   OSStatus status = noErr;   NSLog(@"** original plain text 0: %s", plainBuffer);   size_t plainBufferSize = strlen((char *)plainBuffer);   size_t cipherBufferSize = CIPHER_BUFFER_SIZE;   NSLog(@"SecKeyGetBlockSize() public = %lu", SecKeyGetBlockSize([self getPublicKeyRef]));   //  Error handling   // Encrypt using the public.   status = SecKeyEncrypt([self getPublicKeyRef],                          PADDING,                          plainBuffer,                          plainBufferSize,                          &cipherBuffer[0],                          &cipherBufferSize                          );   NSLog(@"encryption result code: %ld (size: %lu)", status, cipherBufferSize);   NSLog(@"encrypted text: %s", cipherBuffer);}- (void)decryptWithPrivateKey:(uint8_t *)cipherBuffer plainBuffer:(uint8_t *)plainBuffer{   OSStatus status = noErr;   size_t cipherBufferSize = strlen((char *)cipherBuffer);   NSLog(@"decryptWithPrivateKey: length of buffer: %lu", BUFFER_SIZE);   NSLog(@"decryptWithPrivateKey: length of input: %lu", cipherBufferSize);   // DECRYPTION   size_t plainBufferSize = BUFFER_SIZE;   //  Error handling   status = SecKeyDecrypt([self getPrivateKeyRef],                          PADDING,                          &cipherBuffer[0],                          cipherBufferSize,                          &plainBuffer[0],                          &plainBufferSize                          );   NSLog(@"decryption result code: %ld (size: %lu)", status, plainBufferSize);   NSLog(@"FINAL decrypted text: %s", plainBuffer);}- (SecKeyRef)getPrivateKeyRef {   OSStatus resultCode = noErr;   SecKeyRef privateKeyReference = NULL;   //    NSData *privateTag = [NSData dataWithBytes:@"ABCD" length:strlen((const char *)@"ABCD")];   //    if(privateKey == NULL) {   [self generateKeyPair:512];   NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init];   // Set the private key query dictionary.   [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];   [queryPrivateKey setObject:privateTag forKey:(__bridge id)kSecAttrApplicationTag];   [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];   [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];   // Get the key.   resultCode = SecItemCopyMatching((__bridge CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKeyReference);   NSLog(@"getPrivateKey: result code: %ld", resultCode);   if(resultCode != noErr)   {      privateKeyReference = NULL;   }   //        [queryPrivateKey release];   //    } else {   //        privateKeyReference = privateKey;   //    }   return privateKeyReference;}- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{   // Return YES for supported orientations   if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {      return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);   } else {      return YES;   }}- (void)generateKeyPair:(NSUInteger)keySize {   OSStatus sanityCheck = noErr;   publicKey = NULL;   privateKey = NULL;   //  LOGGING_FACILITY1( keySize == 512 || keySize == 1024 || keySize == 2048, @"%d is an invalid and unsupported key size.", keySize );   // First delete current keys.   //  [self deleteAsymmetricKeys];   // Container dictionaries.   NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init];   NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init];   NSMutableDictionary * keyPairAttr = [[NSMutableDictionary alloc] init];   // Set top level dictionary for the keypair.   [keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];   [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits];   // Set the private key dictionary.   [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];   [privateKeyAttr setObject:privateTag forKey:(__bridge id)kSecAttrApplicationTag];   // See SecKey.h to set other flag values.   // Set the public key dictionary.   [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];   [publicKeyAttr setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];   // See SecKey.h to set other flag values.   // Set attributes to top level dictionary.   [keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];   [keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];   // SecKeyGeneratePair returns the SecKeyRefs just for educational purposes.   sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKey, &privateKey);   //  LOGGING_FACILITY( sanityCheck == noErr && publicKey != NULL && privateKey != NULL, @"Something really bad went wrong with generating the key pair." );   if(sanityCheck == noErr  && publicKey != NULL && privateKey != NULL)   {      NSLog(@"Successful");   }   //  [privateKeyAttr release];   //  [publicKeyAttr release];   //  [keyPairAttr release];}@end