iOS钥匙串:更新kSecAttrAccessible

时间:2015-05-19 22:17:30

标签: ios keychain security-framework

我需要更新钥匙串条目的kSecAttrAccessible。我不需要更新实际数据,只需更新辅助功能属性。

首先,我尝试找到该项目,以确保我的查询词典是好的:

sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)(queryPrivateKey), (void *)&privateKeyRef);

这一行成功找到了我正在寻找的项目(返回代码为0)。

然后我使用相同的查询更新kSecAttrAccessible属性:

if (sanityCheck == noErr && privateKeyRef != nil) {
    // found it, update accessibility
    NSMutableDictionary *updatedAttributes = [[NSMutableDictionary alloc] init];
    updatedAttributes[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAlways;
    OSStatus updateItemStatus = SecItemUpdate((__bridge CFDictionaryRef)queryPrivateKey, (__bridge CFDictionaryRef)updatedAttributes);
}

此时,updateItemStatus为-50(paramErr)。

我看过这个帖子:Is it possible to update a Keychain item's kSecAttrAccessible value? 但是我的问题不同了。即使我将kSecValueData添加到updatedAttributes,它也会返回-50。此外,文档还指出我们只需要为iOS 4及更早版本添加kSecValueData。我支持iOS 7及更高版本,所以这不应该成为我的问题。

有人能指出我在这里缺少的东西吗?非常感谢。

1 个答案:

答案 0 :(得分:3)

查询可以通过SecItemCopyMatching成功找到钥匙串项的事实并不意味着可以使用相同的查询来更新钥匙串项。

我使用以下查询进行项目查找:

[queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
[queryPrivateKey setObject:[EncryptionHelper privateKeyTag:JWT_KEYPAIR_TAG] forKey:(__bridge id<NSCopying>)(kSecAttrApplicationTag)];

sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)(queryPrivateKey), (void *)&privateKeyef);

但是,为了将此查询用于项目更新,我首先必须这样做:

[queryPrivateKey removeObjectForKey:(__bridge id)kSecReturnRef];

然后我可以更新:

OSStatus updateItemStatus = SecItemUpdate((__bridge CFDictionaryRef)queryPrivateKey,(__bridge CFDictionaryRef)updatedAttributes);

显然,kSecReturnRef不是SecItemUpdate的查询字典中的可接受键。我无法从Apple文档中找到SecItemUpdate查询的可接受键列表。从SecItemUpdate的文档来看,似乎只有these keys是可以接受的,但这似乎不是正确的列表,因为我期望像kSecClass等密钥在列表。如果有人有更新的文档链接,请分享一下,现在我只需要一些试验和错误就可以找出SecItemUpdate可以接受哪些密钥。

找到该项后,更新kSecAttrAccessible还有另一个复杂因素:您无法从kSecAttrAccessibleWhenUnlocked等较高安全设置更新为kSecAttrAccessibleAlways等较低设置当手机因安全原因被锁定时,移动必须在手机解锁时发生。迁移的一个好地方是应用程序在前台恢复时,因为当应用程序位于前台时,设备必须处于解锁状态。