我想在帐户[email protected]中保存两个值。词典示例:
kSecAttrAccount = [email protected]
kSecAttrGeneric = value1Key
kSecValueData = value1
kSecAttrAccount = [email protected]
kSecAttrGeneric = value2Key
kSecValueData = value2
可能吗?尝试保留第二个值时出现查询错误。
我附上我的代码片段:
func addCredentials(_ credentials: KeychainCredentials) throws {
let account = credentials.account
let password = credentials.password.data(using: String.Encoding.utf8)!
let generic = credentials.generic
let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
.userPresence,
nil)
// Build the query
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceName,
kSecAttrAccount as String: account,
kSecAttrGeneric as String: generic,
kSecAttrAccessControl as String: accessControl as Any,
kSecValueData as String: password]
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else { throw KeychainError(status: status) }
}
最佳答案
对于kSecClassGenericPassword
,服务和帐户的组合必须唯一。有关哪些属性是主键的一部分的列表,请参见errSecDuplicateItem的文档。
当该钥匙串已经具有相同类别的项目且具有相同的一组复合主键时,系统认为该项目是给定钥匙串的重复项。钥匙串项目的每个类别都有一组不同的主键,尽管在所有类别中共有一些属性。特别是,在适用的情况下,kSecAttrSynchronizable和kSecAttrAccessGroup是主键集的一部分。以下列出了每个类别的其他主键:
对于通用密码,主键包括kSecAttrAccount和kSecAttrService。
对于Internet密码,主键包括kSecAttrAccount,kSecAttrSecurityDomain,kSecAttrServer,kSecAttrProtocol,kSecAttrAuthenticationType,kSecAttrPort和kSecAttrPath。
对于证书,主键包括kSecAttrCertificateType,kSecAttrIssuer和kSecAttrSerialNumber。
对于关键项,主键包括kSecAttrKeyClass,kSecAttrKeyType,kSecAttrApplicationLabel,kSecAttrApplicationTag,kSecAttrKeySizeInBits和kSecAttrEffectiveKeySize。
对于身份项目,即证书和私钥捆绑在一起,其主密钥与证书相同。由于可以对私钥进行多次验证,因此证书的唯一性决定了身份的唯一性。
如果要构建此文件,则可能会将所有键/值放入字典中,并将其序列化为单个kSecAttrAccount记录。
或者,您可以将帐户和服务值合并到帐户中(如果您有服务),然后将value1Key
放在service属性中。这样,帐户+服务对于给定密钥将是唯一的。