title: RSA encryption on xcode
body: <p>I'm trying to encrypt a piece of text with RSA using a public key.</p>
  
  <p>This is the code so far:</p>
  
  <pre><code>//EncViewController.h    
  #import &lt;UIKit/UIKit.h&gt;
  
  @interface EncViewController : UIViewController
  {
      SecKeyRef publicKey;
      NSData *publicTag;
  }
  
  - (void)encryptWithPublicKey:(uint8_t *)plainBuffer cipherBuffer:(uint8_t *)cipherBuffer;
  - (SecKeyRef)getPublicKeyRef;
  
  @end
  </code></pre>
  
  <p>And the implementation file:</p>
  
  <pre><code>#import "EncViewController.h"
  
  UInt8 privateKeyIdentifier[] = "-----BEGIN RSA PRIVATE KEY-----\n"
  "MIIEowIBAAKCAQEAqRU6LMhcarK6sgaTgpPEgldUbyBsszsKKpSCDoYqH8fNDpin\n"
  "puYhgR/NDurrZ6t1n3AsyACmmEMbkaxbjJ4Ee8U3zXy3dsbhsshaGWdktlfIipUw\n"
  "4b+ybi4M3T/AcKHSonWw6NWKPLmA/R5nARQMg4tIlRQF6qQPlBaVxk1kHE5NEKxz\n"
  "JaCC01ODsFHEAglDaEMZtGvjGl/hLxI8nqhgLgQsQpU+5ysM4/cmjgqVrU8YzFHp\n"
  "9oMGWdcgQhZR3oJxdrWPn7/Vs5gWKuO6369Pc2kMLv8Tba64uAkNYMQXnMNM+TFy\n"
  "DzNGOAUHkHS70pntrnufsGb8/hRv5nEcZxfd6QIDAQABAoIBAGdUfKfvjmL6dRPk\n"
  "5vLuwTHykrwS8bsawpzBAzZDEa04Wn2oFxTtIN6bg6KxOEmzw/86+3MCyszUfh2p\n"
  "Wo116EGHhhHDPQ+OfVHYFQ/fWvIAdaMTh7r+ftnMtLnlgwKSMnpsOEAieAeiSkzl\n"
  "7ob/LKKbVTEd+nup5YdXwhJdK2gMB1xFLURYi3/ziNXXAb/MxUkldB0B9ZOdDa6Y\n"
  "Ezh1HD2KT3PedZOGuHfXoU2yDi10KeXFjoN6KsOwEJJmicJ1KWevuzYr5zBvZC2N\n"
  "xy6CUHp9iDQONdem1C1cMg/ht4QZpR0Rrz2wRvOxjwUfXd0qel3tBMttHiitRS4u\n"
  "sCF3YwECgYEA3Jj94d1kb0XM5k6y5eS/DODBW+QRI2JRudoQOCnrMnNNYdv6KHvO\n"
  "WfmIDXyw4gi//5NoEDcNf6BPgb487ImXB4AcjMOI0Ox0vNhH300yKbYHF9XgkrvI\n"
  "1aCwE/4QvyBb4zLdt/QxYVxJU9qRC5CsSlqjpsqUBvMhH5mb5DdlMckCgYEAxDfP\n"
  "pFOYHRYYCYDj+Plldf6Z9wSbfp7mOm7j2VvXMgVAlG1HixIcXW10GG0vq3Obpl4Z\n"
  "Li8bik4aX9pN/rRGEgZxNbOc92QkzwkNO00W4L2yHdwD5ONXT8IB8KW7uq3BILld\n"
  "nPm3H9lR+eoLYCbGBJVVAux43uFJHmip8dSKWyECgYAyAxV8AX9losODa1Avwp51\n"
  "wvbTaG9iQEYbBo8qzIYgF/fxObgLOZZc26+2rxBDDozI2ph7JKAQ0T11QrX5QnBV\n"
  "KPxQBXydMR5+OeKBg7TdtAEDrF+PpLcxh46j2bPeQO3UIpIVxGz1j8CoHCNKJfCJ\n"
  "oub7R24r7S8TRPYM1WpB0QKBgBgepC+W9wPcS2gfp+ZbAdXXTiXHMzYFYlecefWm\n"
  "DHXhn2afaEP4HfR+F99IzKtOsrtopb+/mqsNnsBZnWzJzDM7B3+KbKkcbknk2vOH\n"
  "LmDB8Lsq6G+iYoEzX/ms5b60zSCwqIk7SP9pP2JxGqTfH0hA8wpA9zquhsZuJzXK\n"
  "4pcBAoGBAKDJhWP7pM66jrSuxX8+dOlQpb+u6oRkcwEFLEXP7Blz45MJVGGAdjCj\n"
  "hYgz9bg5pNywBiwE1MbBDw/CZejcQk5CgSY0AfDqsBRipHJ7N7KR8aZfpJi4JSgy\n"
  "c5qnAC1sBY/zDjERsOX0CJQfumr5/ae9y637ezvDXVkHcIoNjRxx\n"
  "-----END RSA PRIVATE KEY-----";
  SecKeyRef privateKey;
  NSData *privateTag;
  
  const size_t BUFFER_SIZE = 64;
  const size_t CIPHER_BUFFER_SIZE = 1024;
  size_t FINAL_CIPHER_BUFFER_SIZE;
  const uint32_t PADDING = kSecPaddingPKCS1;
  
  UInt8 publicKeyIdentifier[] = "-----BEGIN PUBLIC KEY-----\n"
  "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqRU6LMhcarK6sgaTgpPE\n"
  "gldUbyBsszsKKpSCDoYqH8fNDpinpuYhgR/NDurrZ6t1n3AsyACmmEMbkaxbjJ4E\n"
  "e8U3zXy3dsbhsshaGWdktlfIipUw4b+ybi4M3T/AcKHSonWw6NWKPLmA/R5nARQM\n"
  "g4tIlRQF6qQPlBaVxk1kHE5NEKxzJaCC01ODsFHEAglDaEMZtGvjGl/hLxI8nqhg\n"
  "LgQsQpU+5ysM4/cmjgqVrU8YzFHp9oMGWdcgQhZR3oJxdrWPn7/Vs5gWKuO6369P\n"
  "c2kMLv8Tba64uAkNYMQXnMNM+TFyDzNGOAUHkHS70pntrnufsGb8/hRv5nEcZxfd\n"
  "6QIDAQAB\n"
  "-----END PUBLIC KEY-----\n";
  
  @interface EncViewController ()
  
  @end
  
  @implementation EncViewController
  
  - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  {
      self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
      if (self) {
          // Custom initialization
      }
      return self;
  }
  
  - (void)didReceiveMemoryWarning
  {
      [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
  }
  
  /*
   #pragma mark - Navigation
  
   // In a storyboard-based application, you will often want to do a little preparation before navigation
   - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
   {
   // Get the new view controller using [segue destinationViewController].
   // Pass the selected object to the new view controller.
   }
   */
  
  - (void)viewDidLoad
  {
      [super viewDidLoad];
      privateTag = [[NSData alloc] initWithBytes:privateKeyIdentifier length:sizeof(privateKeyIdentifier)];
      publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
  
      const char *plainBuffer;
      const char *cipherBuffer;
  
      NSString *textToEncrypt = @"super secret text";
  
  
  
      //const char inputString[] = "How to Encrypt data with public key and Decrypt data with private key";
      int len = strlen(textToEncrypt.UTF8String);
      // TODO: this is a hack since i know inputString length will be less than BUFFER_SIZE
      if (len &gt; BUFFER_SIZE) len = BUFFER_SIZE-1;
  
      plainBuffer = calloc(BUFFER_SIZE, sizeof(uint8_t));
      cipherBuffer = calloc(CIPHER_BUFFER_SIZE, sizeof(uint8_t));
      plainBuffer = [textToEncrypt UTF8String];
      NSLog(@"init() plainBuffer: %s", plainBuffer);
      [self encryptWithPublicKey:plainBuffer cipherBuffer:cipherBuffer];
      NSLog(@"encrypted data: %s", cipherBuffer);
  
      const char *d = cipherBuffer;
      int l = strlen(d);
      NSLog(@"final length: %d",l);
  
      NSData *encodeData = [[NSData alloc] initWithBytes:cipherBuffer length:FINAL_CIPHER_BUFFER_SIZE];
  
      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
      NSString *cachePath = [paths objectAtIndex:0];
      NSLog(@"cache dir: %@",cachePath);
  
      BOOL written = [encodeData writeToFile:[NSString stringWithFormat:@"%@%@",cachePath,@"/test.txt"] atomically:NO];
      NSLog(@"File was writtend: %d",written);
  
      NSString *base64String = [encodeData base64EncodedStringWithOptions:0];
      NSLog(@"Encode String Value: %@", base64String);
  
      free(plainBuffer);
      free(cipherBuffer);
  }
  
  - (NSString *)encryptText:(NSString *)textToEncrypt
  {
      uint8_t *plainBuffer;
      uint8_t *cipherBuffer;
      const char *input = [textToEncrypt UTF8String];
  
      int len = strlen(input);
  
      plainBuffer = (uint8_t *)calloc(len, sizeof(uint8_t));
      cipherBuffer = (uint8_t *)calloc(CIPHER_BUFFER_SIZE, sizeof(uint8_t));
  
      strncpy( (char *)plainBuffer, input, len);
  
      NSLog(@"init() plainBuffer: %s", plainBuffer);
      //NSLog(@"init(): sizeof(plainBuffer): %d", sizeof(plainBuffer));
      [self encryptWithPublicKey:(UInt8 *)plainBuffer cipherBuffer:cipherBuffer];
      NSLog(@"encrypted data: %s", cipherBuffer);
      NSString *s = [NSString stringWithUTF8String:(char *)cipherBuffer];
      NSLog(@"encrypted nsstring %@",s);
      NSData *data = [[NSData alloc] initWithBytes:cipherBuffer length:sizeof(cipherBuffer)];
      NSLog(@"====== /second test =======================================");
  
      free(plainBuffer);
      //free(cipherBuffer);
      return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  }
  
  /* 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);
  
      FINAL_CIPHER_BUFFER_SIZE = CIPHER_BUFFER_SIZE;
  
      NSLog(@"SecKeyGetBlockSize() public = %lu", SecKeyGetBlockSize([self getPublicKeyRef]));
      //  Error handling
      // Encrypt using the public.
      status = SecKeyEncrypt([self getPublicKeyRef],
                             PADDING,
                             plainBuffer,
                             plainBufferSize,
                             &amp;cipherBuffer[0],
                             &amp;FINAL_CIPHER_BUFFER_SIZE
                             );
      NSLog(@"encryption result code: %ld (size: %lu)", status, FINAL_CIPHER_BUFFER_SIZE);
      NSLog(@"encrypted text: %s", cipherBuffer);
  }
  
  -(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 *)&amp;publicKeyReference);
  
  
          if (sanityCheck != noErr)
          {
              publicKeyReference = NULL;
          }
  
  
          //        [queryPublicKey release];
  
      } else {
          publicKeyReference = publicKey;
      }
  
      return publicKeyReference;
  }
  
  - (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, &amp;publicKey, &amp;privateKey);
      //  LOGGING_FACILITY( sanityCheck == noErr &amp;&amp; publicKey != NULL &amp;&amp; privateKey != NULL, @"Something really bad went wrong with generating the key pair." );
      if(sanityCheck == noErr  &amp;&amp; publicKey != NULL &amp;&amp; privateKey != NULL)
      {
          NSLog(@"Successful");
      }
  }
  
  @end
  </code></pre>
  
  <p>Afterwards I'm trying to decrypt the generated encrypted file (test.txt) using the following command from terminal:</p>
  
  <p>cat test.txt | openssl rsautl -pkcs -decrypt -inkey private.pem which should output my decrypted message 
  but I get instead the following error:</p>
  
  <p>RSA operation error
  15328:error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02:/SourceCache/OpenSSL098/OpenSSL098-50/src/crypto/rsa/rsa_pk1.c:190:
  15328:error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed:/SourceCache/OpenSSL098/OpenSSL098-50/src/crypto/rsa/rsa_eay.c:614:</p>
  
  <p>I don't get why since I use the same padding both for encryption in xcode and for decryption using the openssl command...</p>