我使用下面的代码将私钥(端到端加密所需)保存到密钥链中。如果我取出带有kSecAttrSynchronizable as String: kCFBooleanTrue!,
的行,则密钥被正确保存。似乎是这一行导致了错误。我正在尝试获取私钥以在所有iCloud设备上同步。如果你能帮我解决这事我会很感激的。
func save(userUID: String, privatekey: String) {
let passwordData = privatekey.data(using: .utf8)!
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrSynchronizable as String: kCFBooleanTrue!,
kSecAttrService as String: "hustles/\(userUID)",
kSecAttrAccount as String: userUID,
kSecValueData as String: passwordData
]
SecItemAdd(query as CFDictionary, nil)
}
字符串
2条答案
按热度按时间8gsdolmq1#
解决方案是也通过添加“kSecAttrSynchronizable as String:kCFBooleanTrue!保存查询必须与读取查询匹配。
fd3cxomn2#
首先,最好指定
kSecAttrAccessible
key来指示何时可以访问密钥链项,比如kSecAttrAccessibleWhenUnlocked
mentioned here。并确保
kSecAttrService
、kSecAttrAccount
和kSecAttrSynchronizable
的组合必须是唯一的,如explained here。也就是说,
kSecAttrSynchronizable
的存在不应该固有地导致保存操作失败。通常,在这些情况下,最好的方法是检查SecItemAdd
(或其他Keychain API调用)返回的状态,以获得详细的错误信息。正如ahmed的answer中所述,如果你保存的密钥链项具有特定属性(如
kSecAttrSynchronizable
设置为kCFBooleanTrue
),那么当你试图读取(或查询)该项时,你还必须指定 * 相同 * 属性才能成功检索它。保存操作中使用的属性本质上是为密钥链项设置“条件”,当您查询它时,您需要匹配这些条件。因此,如果您保存一个密钥链项时,
kSecAttrSynchronizable
设置为true
,则读取/查询函数也应该包括kSecAttrSynchronizable
设置为true
。如果保存函数是:
字符串
那么你的read函数必须是(灵感来自this answer):
型
kSecMatchLimit as String: kSecMatchLimitOne
确保只返回一个项目(这对我们的用例来说是有意义的,因为每个UID应该只有一个与之相关的私钥)。这样可以确保read函数中的搜索条件与保存项目时设置的属性相匹配,这样您就可以成功地从密钥链中检索它。