Search code examples
objective-cswiftrsapublic-key-encryptionseckeyref

Error casting from AnyObject? to SecKeyRef? in Swift


As part of a Swift based PKI implementation, I ported the SecKeyWrapper.m to Swift

Both, (Objective-C and Swift) of the Keychain access methods are working fine except one part in the Swift implementation.

I receive the public key from the peer in base64 format. It is converted to NSData and then saved in the Keychain using:

statusCode = SecItemAdd(queryDictionary, &persistentPeer)

After successfully saving the peer public key in the keychain, I need to get it as SecKeyRef.

    queryDictionary[kSecReturnPersistentRef] = true
    var peerKeyRef: AnyObject?
    statusCode = SecItemCopyMatching(queryDictionary, &peerKeyRef)

The problem is that SecItemCopyMatching returns an object of type AnyObject? than can´t be casted to SecKeyRef (or SecKey thats is an alias)

let key = peerKeyRef as? SecKeyRef // Compile error.

The work around I found is to cast the peerKeyRef as NSObject? and then use Objective-C to bridge to SecKey as follows:

let keyObject = peerKeyRef as? NSObject
keyRef = Utility.getSecKeyRefFromAnyObject(keyObject).takeRetainedValue()

The Objetive-C code to do it is as follows:

+(SecKeyRef) getSecKeyRefFromNSObject:(id)theObject {
    return (__bridge SecKeyRef)theObject;
}

The casting to SecKey using this workaround works fine (no warnings or errors) with the expected result.

What do you think is missing in the Swift code to cast AnyObject? to SecKeyRef?

I am working with Xcode 7.3.1 and Swift 2.2

Rgds....


Solution

  • That compile error seems to be a bug to me. (Which was once a valid diagnosis when all CF types were imported as typealiases of AnyObject.)

    But in your case I would just do it as:

    let key = peerKeyRef as! SecKeyRef?
    

    You are 100% sure that the query returns SecKeyRef or nil, no?