什么使钥匙串项目独特(在iOS中)?
我的问题涉及iOS(iPhone,iPad,…)中的钥匙链。 我认为(但不是很确定)在Mac OS X下实现钥匙链引发了同样的问题。
iOS提供了五种types的钥匙串项目。 您必须为密钥kSecClass
select这五个值中的kSecClass
来确定types:
kSecClassGenericPassword used to store a generic password kSecClassInternetPassword used to store an internet password kSecClassCertificate used to store a certificate kSecClassKey used to store a kryptographic key kSecClassIdentity used to store an identity (certificate + private key)
经过长时间阅读苹果文档,博客和论坛条目,我发现kSecClassGenericPassword
types的钥匙串项目从属性kSecAttrAccessGroup
, kSecAttrAccount
和kSecAttrService
获得其唯一性。
如果请求1中的这三个属性与请求2中的相同,那么无论其他属性如何,您都会收到相同的通用密码钥匙串项目。 如果一个(或两个或全部)这个属性改变了它的值,那么你会得到不同的项目。
但kSecAttrService
仅适用于kSecClassGenericPassword
types的kSecClassGenericPassword
,因此它不能成为任何其他types项目的“唯一键”的一部分,似乎没有文档明确指出哪些属性唯一确定了一个钥匙串项目。
“GenericKeychain”类的“KeychainItemWrapper”中的示例代码使用属性kSecAttrGeneric
使项目具有唯一性,但这是一个错误。 这个例子中的两个条目仅被存储为两个不同的条目,因为它们的kSecAttrAccessGroup
是不同的(一个访问组已设置,另一个允许它自由)。 如果您尝试使用Apple的KeychainItemWrapper
添加没有访问组的第二个密码,则会失败。
所以,请回答我的问题:
- 是真的,
kSecAttrAccessGroup
,kSecAttrAccount
和kSecAttrService
的组合是kSecClass是kSecClassGenericPassword
的keychain项目的“唯一键”吗? - 如果
kSecClass
不是kSecClassGenericPassword
哪些属性使钥匙串项唯一?
主键如下(从Apple的开源文件派生而来,请参阅Schema.m4 , KeySchema.m4和SecItem.cpp ):
- 对于
kSecClassGenericPassword
类的钥匙串项目,主键是kSecAttrAccount
和kSecAttrService
的组合。 - 对于类
kSecClassInternetPassword
的keychain项,主键是kSecAttrAccount
,kSecAttrSecurityDomain
,kSecAttrServer
,kSecAttrProtocol
,kSecAttrAuthenticationType
,kSecAttrPort
和kSecAttrPath
。 - 对于类
kSecClassCertificate
的keychain项,主键是kSecAttrCertificateType
,kSecAttrIssuer
和kSecAttrSerialNumber
的组合。 - 对于类
kSecClassKey
的keychain项,主键是kSecAttrApplicationLabel
,kSecAttrApplicationTag
,kSecAttrKeyType
,kSecAttrKeySizeInBits
,kSecAttrEffectiveKeySize
和kSecAttrEffectiveKeySize
未公开的创build者,开始date和结束date的组合。 - 对于
kSecClassIdentity
类的keychain项目,我没有find关于开源文件中的主键字段的信息,但是作为一个身份是一个私钥和一个证书的组合,我假设主键是主kSecClassKey
和kSecClassCertificate
关键字段。
由于每个钥匙串项属于钥匙串访问组,所以感觉像钥匙串访问组(字段kSecAttrAccessGroup
)是所有这些主键的添加字段。
我在前一天(在iOS 7.1上)发现了一个与这个问题有关的bug。 我正在使用SecItemCopyMatching
来读取一个kSecClassGenericPassword
项目,并且它仍然返回errSecItemNotFound
(-25300),即使kSecAttrAccessGroup
, kSecAttrAccount
和kSecAttrService
都是匹配钥匙串中的项目。
最终我发现kSecAttrAccessible
不匹配。 钥匙串中的值持有pdmn = dk( kSecAttrAccessibleAlways
),但我使用的是kSecAttrAccessibleWhenUnlocked
。
当然, SecItemCopyMatching
首先不需要这个值,但是OSStatus
不是errSecParam
也不是errSecBadReq
而是errSecItemNotFound
(-25300),这使得它有点棘手。
对于SecItemUpdate
我遇到了同样的问题,但是在这种方法中,即使在query
参数中使用相同的kSecAttrAccessible
也不起作用。 只有彻底删除这个属性才能修复它。
我希望这个评论能为你们中的一些人节省宝贵的debugging时间。