Using Swift 2.2; Xcode 7.3.1 running under El Capitan
Created a private/public key pair with SecKeyGeneratePair Got a copy of my public key using this code ... which I then encode so I can send it across a bluetooth link.
internal func generateKeyPair(publicKeyTag: String, privateKeyTag:String, keySize: Int) {
let privateKeyAttr: [NSString: AnyObject] = [
kSecAttrIsPermanent: true,
kSecAttrApplicationTag: privateKeyTag.dataUsingEncoding(NSUTF8StringEncoding)!
]
let publicKeyAttr: [NSString: AnyObject] = [
kSecAttrIsPermanent: true,
kSecAttrApplicationTag: publicKeyTag.dataUsingEncoding(NSUTF8StringEncoding)!
]
let parameters: [NSString: AnyObject] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits: keySize,
kSecPrivateKeyAttrs: privateKeyAttr,
kSecPublicKeyAttrs: publicKeyAttr
]
let result = SecKeyGeneratePair(parameters, &publicKey, &privateKey)
if errSecSuccess != result {
print("generateKeyPair fail",errSecSuccess, result)
} else {
//print("\(publicKey)\n\n","\(privateKey)")
var dataPtr: AnyObject?
let query: [NSString:AnyObject] = [
kSecClass: kSecClassKey,
kSecAttrApplicationTag: publicKeyTag.dataUsingEncoding(NSUTF8StringEncoding)!,
kSecReturnData: true
]
let qResult = SecItemCopyMatching(query, &dataPtr)
if (qResult == errSecSuccess) {
let PublicKeyText = dataPtr as? NSData
base64Encoded = PublicKeyText!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
print("PublicKeyText \(base64Encoded)")
}
}
}
Now I can unencoded my base64EncodedString blob with this code ...
let data = NSData(base64EncodedString: superString8, options: NSDataBase64DecodingOptions(rawValue:0))
But how to get it back to a usable SecKey object using Swift?I found this reference and started to translate it; but I fear I am way out of my depth here?
get SecKeyRef from base64 coded string
This is what I managed so far ..
let cert:SecCertificateRef!
let policy:SecPolicyRef!
cert = SecCertificateCreateWithData(kCFAllocatorDefault, data!)
policy = SecPolicyCreateBasicX509();
//var status:OSStatus!
var publicKey: SecKeyRef!
//var publicKeyPtr = withUnsafeMutablePointer(&publicKey, { $0 })
var trust:SecTrust?
let trustPtr = withUnsafeMutablePointer(&trust , { $0} )
var certArray:[SecCertificateRef] = []
certArray.append(cert)
var unsafeVariable:UnsafePointer<Void>
let certArrayPtr = withUnsafeMutablePointer(&unsafeVariable, {$0})
var newTrustType: SecTrustResultType = UInt32(kSecTrustResultInvalid)
let newTrustTypePtr = withUnsafeMutablePointer(&newTrustType, {$0})
if (cert != nil) {
//certArray[1] = {cert}()
// let certs:[SecCertificateRef] = CFArrayCreate(kCFAllocatorDefault, certArrayPtr, 1, nil) as! [SecCertificateRef]
let certs:[SecCertificateRef] = CFArrayCreate(kCFAllocatorDefault, certArrayPtr, 1, nil) as! [SecCertificateRef]
var status = SecTrustCreateWithCertificates(certs, policy, trustPtr)
if (status == errSecSuccess){
//status = SecTrustEvaluate(trust!, trustTypePtr)
status = SecTrustEvaluate(trust!, newTrustTypePtr)
// Evaulate the trust.
switch (Int(newTrustType)) {
case kSecTrustResultInvalid: break
case kSecTrustResultDeny: break
case kSecTrustResultUnspecified: break
case kSecTrustResultFatalTrustFailure: break
case kSecTrustResultOtherError: break
case kSecTrustResultRecoverableTrustFailure:
publicKey = SecTrustCopyPublicKey(trust!);
break;
case kSecTrustResultProceed:
publicKey = SecTrustCopyPublicKey(trust!);
break;
}
}
}
} else {
superString8 = superString8 + stringFromData!
}
}