I am saving a private key to keychain and now want to retrieve it but some how not able to do it. Following is my code:
public func storeKeyToKeychain(_ key: SecKey, tag: String) -> Bool {
let deleteQuery: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: tag.data(using: .utf8)!
]
SecItemDelete(deleteQuery as CFDictionary) // Clean existing key before adding
let query: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: tag.data(using: .utf8)!,
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecValueRef as String: key,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
let status = SecItemAdd(query as CFDictionary, nil)
if status != errSecSuccess {
print("Key storage failed with status: \(status) (\(SecCopyErrorMessageString(status, nil) ?? "Unknown error" as CFString))")
} else {
print("Key stored successfully.")
}
return status == errSecSuccess
}
public func getKeyFromKeychain(tag: String) -> SecKey? {
let query: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: tag.data(using: .utf8)!, // Ensure tag is Data
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecReturnRef as String: true // Retrieve the SecKey reference
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
if status == errSecSuccess, let key = item as! SecKey? {
print("Successfully retrieved SecKey.")
return key
} else if status == errSecItemNotFound {
print("Key not found in the Keychain.")
} else {
print("Keychain retrieval failed with status: \(status) (\(SecCopyErrorMessageString(status, nil) ?? "Unknown error" as CFString))")
}
return nil
}
I can see the Key stored successfully message. So key is saved but when I try to fetch it, I getting nil in item which means I am not able to fetch it. I have checked in logs that errSecSuccess is true while fetching it but still I am unable to get the key in item.
kSecAttrKeyType. Have you tried removing this from the queries for adding and getting? Note, that the key itself has been created with an attribute kSecAttrKeyType. Possibly it conflicts with your setting in the query and what actually has been set when creating it?