6

Following Apple example code in: http://developer.apple.com/library/ios/#documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html

I'm able to successfully generate key-pair with the code snippet below, but unable to print the keys...

The function SecKeyGeneratePair() - returns the keys as SecKeyRef type.

I have no idea how to handle this type, I understand that this is the keychain representation but how can I actually view the key-pair as NSString?? More specifically, how to convert SecKeyRef to NSString??

static const UInt8 publicKeyIdentifier[] = "com.apple.sample.publickey\0";
static const UInt8 privateKeyIdentifier[] = "com.apple.sample.privatekey\0";
                                                            // 1


- (void)generateKeyPairPlease
{
    OSStatus status = noErr;
    NSMutableDictionary *privateKeyAttr = [[NSMutableDictionary alloc] init];
    NSMutableDictionary *publicKeyAttr = [[NSMutableDictionary alloc] init];
    NSMutableDictionary *keyPairAttr = [[NSMutableDictionary alloc] init];
                                                                // 2

    NSData * publicTag = [NSData dataWithBytes:publicKeyIdentifier
                                length:strlen((const char *)publicKeyIdentifier)];
    NSData * privateTag = [NSData dataWithBytes:privateKeyIdentifier
                               length:strlen((const char *)privateKeyIdentifier)];
                                                                // 3

    SecKeyRef publicKey = NULL;
    SecKeyRef privateKey = NULL;                                // 4

    [keyPairAttr setObject:(id)kSecAttrKeyTypeRSA
                                   forKey:(id)kSecAttrKeyType]; // 5
    [keyPairAttr setObject:[NSNumber numberWithInt:1024]
                             forKey:(id)kSecAttrKeySizeInBits]; // 6

    [privateKeyAttr setObject:[NSNumber numberWithBool:YES]
                               forKey:(id)kSecAttrIsPermanent]; // 7
    [privateKeyAttr setObject:privateTag
                            forKey:(id)kSecAttrApplicationTag]; // 8

    [publicKeyAttr setObject:[NSNumber numberWithBool:YES]
                               forKey:(id)kSecAttrIsPermanent]; // 9
    [publicKeyAttr setObject:publicTag
                            forKey:(id)kSecAttrApplicationTag]; // 10

    [keyPairAttr setObject:privateKeyAttr
                               forKey:(id)kSecPrivateKeyAttrs]; // 11
    [keyPairAttr setObject:publicKeyAttr
                                forKey:(id)kSecPublicKeyAttrs]; // 12

    status = SecKeyGeneratePair((CFDictionaryRef)keyPairAttr,
                                      &publicKey, &privateKey); // 13
//    error handling...


    if(privateKeyAttr) [privateKeyAttr release];
    if(publicKeyAttr) [publicKeyAttr release];
    if(keyPairAttr) [keyPairAttr release];
    if(publicKey) CFRelease(publicKey);
    if(privateKey) CFRelease(privateKey);                       // 14
}
Oded Regev
  • 4,065
  • 2
  • 38
  • 50

3 Answers3

7

You can use SecItemCopyMatching to get key's NSData. Check getPublicKeyBits method in Apple's CryptoExercise, it implements exactly what you need.

Then you can convert NSData to a string. Perhaps, Base64 encoding will suite your needs. Here you can find Base64 encoding/decoding sample for iPhone. Alternatively, this answer may also be useful for Base64 encoding.

Community
  • 1
  • 1
tenorsax
  • 21,123
  • 9
  • 60
  • 107
  • 1
    thank you, I use the getPublicKeyBits and I do receive the value as NSData, there is something weird though, when creating the keypair I specify kSecAttrKeySizeInBits = 1024, but the NSData size (received from getPublicKeyBits) is 140 bytes (instead of the expected 128) any idea why?? – Oded Regev Apr 09 '12 at 10:55
  • 2
    This is probably due to the format that is used to store keys. I'm not sure what is the reason you're printing the keys. Checkout [this](http://blog.wingsofhermes.org/?p=42) and [this](http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/) links that discuss ways to work with iOS keys. – tenorsax Apr 09 '12 at 18:45
  • I can get the NSData and generate a NSString use: `[data base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength]; [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];`. But can not use this NSString to encrypt . SOS – Crazy Catcher Aug 17 '16 at 16:04
2

You can use https://github.com/henrinormak/Heimdall

let localHeimdall = Heimdall(tagPrefix: "com.example")

if let heimdall = localHeimdall {
    let publicKeyData = heimdall.X509PublicKey()
    var publicKeyString = publicKeyData.base64EncodedStringWithOptions(.allZeros)

    // If you want to make this string URL safe,
    // you have to remember to do the reverse on the other side later
    publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("/", withString: "_")
    publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("+", withString: "-")

    println(publicKeyString) // Something along the lines of "MIGfMA0GCSqGSIb3DQEBAQUAA..."

    // Data transmission of public key to the other party
}

swift 3:

let localHeimdall = Heimdall(tagPrefix: "com.example")
if let heimdall = localHeimdall, publicKeyData = heimdall.publicKeyDataX509() {

    var publicKeyString = publicKeyData.base64EncodedString()

    // If you want to make this string URL safe,
    // you have to remember to do the reverse on the other side later
    publicKeyString = publicKeyString.replacingOccurrences(of: "/", with: "_")
    publicKeyString = publicKeyString.replacingOccurrences(of: "+", with: "-")

    println(publicKeyString) // Something along the lines of "MIGfMA0GCSqGSIb3DQEBAQUAA..."

    // Data transmission of public key to the other party
}
phnmnn
  • 12,813
  • 11
  • 47
  • 64
0
-(void)writePublicKeyModAndExp
{
  KeyHelper* keyHelper =[[KeyHelper alloc]init];
  NSData* pubkeyData=  [keyHelper getPublicKeyBitsWithtag:publicTag];

  NSLog(@"pubKey :%@",[pubkeyData base64Encoding]);

  NSData *modData=  [keyHelper getPublicKeyModFromKeyData:pubkeyData];
  NSLog(@"modulus :%@",[modData base64Encoding]);

  NSData *expoData=  [keyHelper getPublicKeyExpFromKeyData:pubkeyData];
  NSLog(@"exponent :%@",[expoData base64Encoding]);
}

You can find whole code here https://github.com/ozgurshn/EncryptionForiOS

Ozgur Sahin
  • 1,305
  • 16
  • 24