Generate key pair on iphone and print to log as NSString

14,741

Solution 1

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.

Solution 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
}
Share:
14,741
Oded Regev
Author by

Oded Regev

Updated on June 30, 2022

Comments

  • Oded Regev
    Oded Regev almost 2 years

    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
    Oded Regev about 12 years
    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??
  • tenorsax
    tenorsax about 12 years
    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 and this links that discuss ways to work with iOS keys.
  • Crazy Catcher
    Crazy Catcher over 7 years
    I can get the NSData and generate a NSString use: [data base64EncodedDataWithOptions:NSDataBase64Encoding64Character‌​LineLength]; [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];. But can not use this NSString to encrypt . SOS