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
Avplayerlayer Shows Black Screen But Sound Is Working
Didoutputsamplebuffer Delegate Not Called
Can't Copy File from Bundle to Documents Directory in iOS
Updating Label Takes Too Long (Swift)
Find Delegate in a Swift Array of Delegates
Longer Subtitles in Mapview Annotations (Swift)
How to Make App Wait Until Firebase Request Is Finished
How to Catch Nsunknownkeyexception in Swift 2.2
How to Make Playground Execution Time Is as Fast as If We Run in iOS Application
Coretelephony Esim Functions Not Working on Device
Animating Strings Fading In/Out in Swift
How to Get Only Keys from Firebase
How to Make Watchkit Extension App and My iPhone App Share the Same Icloud Databases