我的问题涉及iOS(iPhone,iPad,...)中的钥匙串 . 我认为(但不确定)Mac OS X下的钥匙串的实现会用相同的答案提出同样的问题 .
iOS提供五种类型(类)的钥匙串项 . 您必须为键 kSecClass
选择这五个值中的一个来确定类型:
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
类型的钥匙串项从属性 kSecAttrAccessGroup
, kSecAttrAccount
和 kSecAttrService
获得其唯一性 .
如果请求1中的这三个属性与请求2中的相同,则无论其他任何属性如何,您都会收到相同的通用密码keychain项 . 如果此属性中的一个(或两个或全部)更改其值,则会获得不同的项目 .
但 kSecAttrService
仅适用于 kSecClassGenericPassword
类型的项目,因此它不能是任何其他类型项目的"unique key"的一部分,并且似乎没有文档明确指出哪些属性唯一地确定了钥匙串项目 .
"KeychainItemWrapper"类"KeychainItemWrapper"中的示例代码使用属性 kSecAttrGeneric
使项目唯一,但这是一个错误 . 此示例中的两个条目仅存储为两个不同的条目,因为它们的 kSecAttrAccessGroup
不同(一个设置了访问组,另一个允许它自由) . 如果您尝试使用Apple的 KeychainItemWrapper
添加没有访问组的第二个密码,则会失败 .
So, please, answer my questions:
-
这是真的,
kSecAttrAccessGroup
,kSecAttrAccount
和kSecAttrService
的组合是一个钥匙串项的"unique key",其kSecClass是kSecClassGenericPassword
? -
如果
kSecClass
不是kSecClassGenericPassword
,哪个属性会使钥匙串项目唯一?
3 回答
我前几天(在iOS 7.1上)遇到了与此问题相关的错误 . 我正在使用
SecItemCopyMatching
读取kSecClassGenericPassword
项目并且它仍然返回errSecItemNotFound
(-25300),即使kSecAttrAccessGroup
,kSecAttrAccount
和kSecAttrService
都与钥匙串中的项目匹配 .最终我发现
kSecAttrAccessible
不匹配 . 钥匙串中的值持有pdmn = dk(kSecAttrAccessibleAlways
),但我使用的是kSecAttrAccessibleWhenUnlocked
.当然
SecItemCopyMatching
首先不需要这个值,但是OSStatus
不是errSecParam
也不是errSecBadReq
而是errSecItemNotFound
(-25300)这使得查找有点棘手 .对于
SecItemUpdate
我遇到了同样的问题,但在这种方法中,即使在query
参数中使用相同的kSecAttrAccessible
也不起作用 . 只有完全删除此属性才能修复它 .我希望这个评论能为你们中的一些人节省一些宝贵的调试时间 .
主键如下(从Apple的开源文件派生,请参阅Schema.m4,KeySchema.m4和SecItem.cpp):
对于类
kSecClassGenericPassword
的钥匙串项,主键是kSecAttrAccount
和kSecAttrService
的组合 .对于类
kSecClassInternetPassword
的钥匙串项,主键是kSecAttrAccount
,kSecAttrSecurityDomain
,kSecAttrServer
,kSecAttrProtocol
,kSecAttrAuthenticationType
,kSecAttrPort
和kSecAttrPath
的组合 .对于类
kSecClassCertificate
的钥匙串项,主键是kSecAttrCertificateType
,kSecAttrIssuer
和kSecAttrSerialNumber
的组合 .对于类
kSecClassKey
的钥匙串项,主键是kSecAttrApplicationLabel
,kSecAttrApplicationTag
,kSecAttrKeyType
,kSecAttrKeySizeInBits
,kSecAttrEffectiveKeySize
的组合,以及SecItem尚未公开的创建者,开始日期和结束日期 .对于
kSecClassIdentity
类的钥匙串项目,我没有找到开源文件中主键字段的信息,但由于标识是私钥和证书的组合,我假设主键是kSecClassKey
和kSecClassCertificate
的主键字段 .由于每个钥匙串项属于钥匙串访问组,感觉钥匙串访问组(字段
kSecAttrAccessGroup
)是所有这些主键的添加字段 .@Tammo Freese给出的答案似乎是正确的(但没有提到所有主键) . 我在文档中搜索了一些证据 . 终于找到了:
Apple Documentation mentioning primary keys for each class of secret (quote below):