4

Im attempting to implement an RSA encryption algorithm into my iOS app, but when I attempt to generate a public and private key pair, the function returns me the errSecUnimplemented error. I am using the 5.1 SDK and targeting 5.1 at the moment.

Can I not use this function, or did I set up something wrong in attempting to generate the pair?

Here is my code for the key generation:

SecKeyRef publicKey, privateKey;
CFDictionaryRef parameters;
const void* keys[] = {kSecAttrKeyType, kSecAttrKeyTypeRSA};
int keySize = 1024;
const void *values[] = {kSecAttrKeySizeInBits, &keySize};

parameters = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 2, NULL, NULL);
OSStatus ret = SecKeyGeneratePair(parameters, &publicKey, &privateKey);
if ( ret == errSecSuccess )
{
    NSLog(@"Key success!");
}
else 
{
    NSLog(@"Key Failure! %li", ret);
}
Dan F
  • 17,654
  • 5
  • 72
  • 110

3 Answers3

9

I've revised it to just complete the solution for you. 1) You need to use a CFNumberRef and not a pointer to an int for the numerical value. 2) The values need to be the values, the keys need to be the keys - you were mixing a key and value in each of "keys" and "values".

SInt32 iKeySize = 1024;
CFNumberRef keySize = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &iKeySize);
const void* values[] = { kSecAttrKeyTypeRSA, keySize };
const void* keys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits };
CFDictionaryRef parameters = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 2, NULL, NULL);

SecKeyRef publicKey, privateKey;
OSStatus ret = SecKeyGeneratePair(parameters, &publicKey, &privateKey);
if ( ret == errSecSuccess )
    NSLog(@"Key success!");
else 
    NSLog(@"Key Failure! %li", ret);
NSProgrammer
  • 2,387
  • 1
  • 24
  • 27
  • I get the following error with ARC enabled: `Use __bridge_retained to make an ARC object available as a +1 'CFTypeRef' (aka 'const void *')` Last time I tried to use a `__bridge` cast everything went haywire, is this a simpler, but safe case to do so? – Dan F May 14 '12 at 13:27
  • And even if I do a `__bridge_retained` cast, I still get the -4 error – Dan F May 14 '12 at 13:28
  • Edited to be complete. You should be good to go (so long as I didn't leave any typos). – NSProgrammer May 15 '12 at 14:56
  • I get a warning with your code because `values` is of type `void*` not `void**`, and if I make it into `const void* values[]` i get a bad access exception, and still the -4 error if I leave it as just a `const void *` – Dan F May 15 '12 at 15:13
  • Apologies, you should pass the ref to your keys and values, edited – NSProgrammer May 15 '12 at 19:33
  • Those still aren't the right types. `CFDictionaryCreate` is looking for two `const void **`, and `keys` by itself is a `const void **` adding the reference to it, you're making it a `const void ***`, and in your latest edit, `values` is still written as just a `const void *`, not a `const void *[]` – Dan F May 15 '12 at 19:36
  • Oh man... I see it now. I didn't put the array parens for one of the declarations. I should mention I'm doing this all on my iPhone. – NSProgrammer May 15 '12 at 23:02
  • I tried that combination, and that is how I end up with an EXC_BAD_ACCESS exception being thrown on `SecKeyGeneratePair` – Dan F May 16 '12 at 13:07
  • That's what I get for not checking my work with a compiler. values needed the CFNumberRef itself, not a reference to it. Code updated... – NSProgrammer May 16 '12 at 13:29
  • Ah HA! Finally success! Thank you for all your help, I searched for quite a while to find sample code for this method, but just nothing existed anywhere... – Dan F May 16 '12 at 13:58
  • Yay! The power of crowd sourcing and persistence! :) – NSProgrammer May 16 '12 at 14:01
  • For those using the example code here, 1024 bit RSA keys aren't considered secure anymore, you should use 2048 or 4096 bit keys instead. – Michael Barnwell Jan 30 '18 at 13:51
  • Do we have this in swift? – Mike May 29 '20 at 17:20
0

Shouldn't this be:

const void* keys[] = {kSecAttrKeyType, kSecAttrKeySizeInBits};
int keySize = 1024;
const void *values[] = {kSecAttrKeyTypeRSA, &keySize};

i.e., the keys should be the keys of the dict and the values the values, currently you have one (key,value) pair in keys and one in values.

Arno Bakker
  • 329
  • 1
  • 4
  • I get a bad access exception when I do it this way, even with setting the key size as nob outlined above – Dan F May 15 '12 at 13:01
  • Perhaps http://www.iphonedevsdk.com/forum/iphone-sdk-development/7339-rsa-encryption.html helps. – Arno Bakker May 23 '12 at 11:21
0

Using kCFAllocatorSystemDefault instead of kCFAllocatorDefault return errSecSuccess.

user
  • 86,916
  • 18
  • 197
  • 190