首页 文章

是什么让钥匙串项目独一无二(在iOS中)?

提问于
浏览
87

我的问题涉及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 类型的钥匙串项从属性 kSecAttrAccessGroupkSecAttrAccountkSecAttrService 获得其唯一性 .

如果请求1中的这三个属性与请求2中的相同,则无论其他任何属性如何,您都会收到相同的通用密码keychain项 . 如果此属性中的一个(或两个或全部)更改其值,则会获得不同的项目 .

kSecAttrService 仅适用于 kSecClassGenericPassword 类型的项目,因此它不能是任何其他类型项目的"unique key"的一部分,并且似乎没有文档明确指出哪些属性唯一地确定了钥匙串项目 .

"KeychainItemWrapper"类"KeychainItemWrapper"中的示例代码使用属性 kSecAttrGeneric 使项目唯一,但这是一个错误 . 此示例中的两个条目仅存储为两个不同的条目,因为它们的 kSecAttrAccessGroup 不同(一个设置了访问组,另一个允许它自由) . 如果您尝试使用Apple的 KeychainItemWrapper 添加没有访问组的第二个密码,则会失败 .

So, please, answer my questions:

  • 这是真的, kSecAttrAccessGroupkSecAttrAccountkSecAttrService 的组合是一个钥匙串项的"unique key",其kSecClass是 kSecClassGenericPassword

  • 如果 kSecClass 不是 kSecClassGenericPassword ,哪个属性会使钥匙串项目唯一?

3 回答

  • 0

    我前几天(在iOS 7.1上)遇到了与此问题相关的错误 . 我正在使用 SecItemCopyMatching 读取 kSecClassGenericPassword 项目并且它仍然返回 errSecItemNotFound (-25300),即使 kSecAttrAccessGroupkSecAttrAccountkSecAttrService 都与钥匙串中的项目匹配 .

    最终我发现 kSecAttrAccessible 不匹配 . 钥匙串中的值持有pdmn = dk( kSecAttrAccessibleAlways ),但我使用的是 kSecAttrAccessibleWhenUnlocked .

    当然 SecItemCopyMatching 首先不需要这个值,但是 OSStatus 不是 errSecParam 也不是 errSecBadReq 而是 errSecItemNotFound (-25300)这使得查找有点棘手 .

    对于 SecItemUpdate 我遇到了同样的问题,但在这种方法中,即使在 query 参数中使用相同的 kSecAttrAccessible 也不起作用 . 只有完全删除此属性才能修复它 .

    我希望这个评论能为你们中的一些人节省一些宝贵的调试时间 .

  • 8

    主键如下(从Apple的开源文件派生,请参阅Schema.m4KeySchema.m4SecItem.cpp):

    • 对于类 kSecClassGenericPassword 的钥匙串项,主键是 kSecAttrAccountkSecAttrService 的组合 .

    • 对于类 kSecClassInternetPassword 的钥匙串项,主键是 kSecAttrAccountkSecAttrSecurityDomainkSecAttrServerkSecAttrProtocolkSecAttrAuthenticationTypekSecAttrPortkSecAttrPath 的组合 .

    • 对于类 kSecClassCertificate 的钥匙串项,主键是 kSecAttrCertificateTypekSecAttrIssuerkSecAttrSerialNumber 的组合 .

    • 对于类 kSecClassKey 的钥匙串项,主键是 kSecAttrApplicationLabelkSecAttrApplicationTagkSecAttrKeyTypekSecAttrKeySizeInBitskSecAttrEffectiveKeySize 的组合,以及SecItem尚未公开的创建者,开始日期和结束日期 .

    • 对于 kSecClassIdentity 类的钥匙串项目,我没有找到开源文件中主键字段的信息,但由于标识是私钥和证书的组合,我假设主键是 kSecClassKeykSecClassCertificate 的主键字段 .

    由于每个钥匙串项属于钥匙串访问组,感觉钥匙串访问组(字段 kSecAttrAccessGroup )是所有这些主键的添加字段 .

  • 144

    @Tammo Freese给出的答案似乎是正确的(但没有提到所有主键) . 我在文档中搜索了一些证据 . 终于找到了:

    Apple Documentation mentioning primary keys for each class of secret (quote below):

    当该钥匙串已经具有具有相同复合主键集的相同类的项时,系统将该项视为给定钥匙串的副本 . 每类钥匙串项都有一组不同的主键,尽管在所有类中都有一些共同的属性 . 特别是,在适用的情况下,kSecAttrSynchronizable和kSecAttrAccessGroup是主键集的一部分 . 下面列出了额外的每类主键:对于通用密码,主键包括kSecAttrAccount和kSecAttrService . 对于Internet密码,主键包括kSecAttrAccount,kSecAttrSecurityDomain,kSecAttrServer,kSecAttrProtocol,kSecAttrAuthenticationType,kSecAttrPort和kSecAttrPath . 对于证书,主键包括kSecAttrCertificateType,kSecAttrIssuer和kSecAttrSerialNumber . 对于关键项,主键包括kSecAttrKeyClass,kSecAttrKeyType,kSecAttrApplicationLabel,kSecAttrApplicationTag,kSecAttrKeySizeInBits和kSecAttrEffectiveKeySize . 对于作为证书和捆绑在一起的私钥的身份项,主键与证书相同 . 由于私钥可能被多次认证,因此证书的唯一性决定了身份的唯一性 .

相关问题