Retrieve Seckey from Keychain

Saving and Reading SecKey to Keychain

Your query doesn't request the key you put it. It requests "the first key I have access to." You need some kind of identifier to distinguish the key you're inserting, and then use that identifier to search for it.

For keys, the "label" (kSecAttrApplicationLabel) should automatically be set to the hash of the public key. Alternately, you can set and search for the tag (kSecAttrApplicationTag) which is any arbitrary data you'd like to use to identify this key.

Keep in mind that the keys are considered unique based on both their label (hash) and tag, which means that you can have multiple keys in the keychain with the same tag. Your test case should, at a minimum, delete any keys it creates. Your code probably also needs to be resilient to situations where there are multiple keys with the same tag if you use tags rather than labels/hashes to identify keys.

How do I export a public key SecKey that was generated using SecKeyGeneratePair to be used on a server?

SecItemCopyMatching is for you:

var dataPtr:Unmanaged<AnyObject>?
let query: [String:AnyObject] = [
kSecClass: kSecClassKey,
kSecAttrApplicationTag: "com.example.site.public",
kSecReturnData: kCFBooleanTrue
]
let qResult = SecItemCopyMatching(query, &dataPtr)

// error handling with `qResult` ...

let publicKeyData = dataPtr!.takeRetainedValue() as NSData

// convert to Base64 string
let base64PublicKey = publicKeyData.base64EncodedStringWithOptions(nil)

Swift 4:

var dataPtr:CFTypeRef?
let query: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: "com.example.site.public",
kSecReturnData as String: true
]

let qResult = SecItemCopyMatching(query as CFDictionary, &dataPtr)

// error handling with `qResult` ...

let data = dataPtr as! Data
let base64PublicKey = data.base64EncodedString()

Note that the size of the data is 270, not the same as block size of the key. See this question on the crypto.stackexchange.com.

Is there any way to get the key type of a SecKey?

You can retrieve the kSecAttrKeyType from the key and check if it is kSecAttrKeyTypeRSA (or kSecAttrKeyTypeEC). Example (taken from SwiftyRSA):

func isRSAKey(seckey: SecKey) -> Bool {
guard let attributes = SecKeyCopyAttributes(seckey) as? [CFString: Any],
let keyType = attributes[kSecAttrKeyType] as? String else {
return false
}

let isRSA = keyType == (kSecAttrKeyTypeRSA as String)
return isRSA
}


Related Topics



Leave a reply



Submit