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
}
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.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With