我正在将私钥保存到钥匙串中,现在想要检索它,但有些无法做到。以下是我的代码:
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
}
我可以看到密钥存储成功的消息。因此,密钥已保存,但当我尝试获取它时,项目中的值为零,这意味着我无法获取它。 我在日志中检查了在获取它时 errSecSuccess 为 true,但我仍然无法获取 item 中的密钥。
尝试使用此代码。我正在使用这个,效果很好。
class KeychainAccess {
func addKeychainData(itemKey: String, itemValue: String) throws {
guard let valueData = itemValue.data(using: .utf8) else {
print("Keychain: Unable to store data, invalid input - key: \(itemKey), value: \(itemValue)")
return
}
//delete old value if stored first
do {
try deleteKeychainData(itemKey: itemKey)
} catch {
print("Keychain: nothing to delete...")
}
let queryAdd: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: itemKey as AnyObject,
kSecValueData as String: valueData as AnyObject,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
let resultCode: OSStatus = SecItemAdd(queryAdd as CFDictionary, nil)
if resultCode != 0 {
print("Keychain: value not added - Error: \(resultCode)")
} else {
print("Keychain: value added successfully")
}
}
func deleteKeychainData(itemKey: String) throws {
let queryDelete: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: itemKey as AnyObject
]
let resultCodeDelete = SecItemDelete(queryDelete as CFDictionary)
if resultCodeDelete != 0 {
print("Keychain: unable to delete from keychain: \(resultCodeDelete)")
} else {
print("Keychain: successfully deleted item")
}
}
func queryKeychainData (itemKey: String) throws -> String? {
let queryLoad: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: itemKey as AnyObject,
kSecReturnData as String: kCFBooleanTrue,
kSecMatchLimit as String: kSecMatchLimitOne
]
var result: AnyObject?
let resultCodeLoad = withUnsafeMutablePointer(to: &result) {
SecItemCopyMatching(queryLoad as CFDictionary, UnsafeMutablePointer($0))
}
if resultCodeLoad != 0 {
print("Keychain: unable to load data - \(resultCodeLoad)")
return nil
}
guard let resultVal = result as? NSData, let keyValue = NSString(data: resultVal as Data, encoding: String.Encoding.utf8.rawValue) as String? else {
print("Keychain: error parsing keychain result - \(resultCodeLoad)")
return nil
}
return keyValue
}
}
创建一个对象并使用该对象来存储和获取。
let keychain = KeychainAccess()
do {
try? self.keychain.addKeychainData(itemKey: "KeyChainUserName", itemValue: result?.customer?.email ?? "")
} catch {
print("error of user Name")
}
do {
try? self.keychain.addKeychainData(itemKey: "KeyChainPassword", itemValue: "\(result?.customer?.id ?? 0)" )
} catch {
print("error of password")
}
从钥匙串中获取数据。
let userName = try? self.keychain.queryKeychainData(itemKey: "KeyChainUserName")
print("UserName:", userNam)