是否可以更新Keychain中现有项的属性kSecAttrAccessible
的值?项目被添加到钥匙串后似乎无法更改。以下步骤支持我的假设。
向钥匙串添加新项目:
NSData *encodedIdentifier = [@"BUNDLE_IDENTIFIER"
dataUsingEncoding:NSUTF8StringEncoding];
NSData *encodedPassword = [@"PASSWORD"
dataUsingEncoding:NSUTF8StringEncoding];
// Construct a Keychain item
NSDictionary *keychainItem =
[NSDictionary dictionaryWithObjectsAndKeys:
kSecClassGenericPassword, kSecClass,
encodedIdentifier, kSecAttrGeneric,
encodedIdentifier, kSecAttrService,
@"USERNAME", kSecAttrAccount,
kSecAttrAccessibleWhenUnlocked, kSecAttrAccessible,
encodedPassword, kSecValueData
nil];
// Add item to Keychain
OSStatus addItemStatus = SecItemAdd((CFDictionaryRef)keychainItem, NULL);
稍后,将属性kSecAttrAccessible
从kSecAttrAccessibleWhenUnlocked
更改为kSecAttrAccessibleAfterFirstUnlock
:
NSData *encodedIdentifier = [@"BUNDLE_IDENTIFIER"
dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
kSecClassGenericPassword, kSecClass,
encodedIdentifier, kSecAttrGeneric,
encodedIdentifier, kSecAttrService,
nil];
NSDictionary *updatedAttributes =
[NSDictionary dictionaryWithObject:kSecAttrAccessibleAfterFirstUnlock
forKey:kSecAttrAccessible];
OSStatus updateItemStatus = SecItemUpdate((CFDictionaryRef)query,
(CFDictionaryRef)updatedAttributes);
此方法的问题是updateItemStatus
始终会导致状态errSecUnimplemented
。
我认为应该可以更新kSecAttrAccessible
的值,因为应用程序的要求会发生变化。如果应用程序过去在Keychain中添加了10个项目而未指定具有kSecAttrAccessible
的保护类,该怎么办?如果开发人员未明确设置保护类,则Keychain会隐式地为值kSecAttrAccessibleWhenUnlocked
分配新项。稍后,开发人员需要将保护类更改为kSecAttrAccessibleAfterFirstUnlock
,因为应用程序必须在后台访问它(多任务处理)。开发人员如何实现这一目标?
Apple开发者论坛中已有一个主题,但尚未得出答案:https://devforums.apple.com/thread/87646?tstart=0
答案 0 :(得分:19)
在Apple开发者技术支持(ADTS)开启支持事件后,我收到了回复此问题的回复。 SecItemUpdate()
需要通过属性kSecValueData
的Keychain项目数据来执行属性kSecAttrAccessible
的更新。根据ADTS,此约束目前未在参考文档中记录。
NSData *encodedIdentifier = [@"BUNDLE_IDENTIFIER"
dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
kSecClassGenericPassword, kSecClass,
encodedIdentifier, kSecAttrGeneric,
encodedIdentifier, kSecAttrService,
nil];
// Obtain the Keychain item's data via SecItemCopyMatching()
NSData *itemData = ...;
NSDictionary *updatedAttributes =
[NSDictionary dictionaryWithObjectsAndKeys:
kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessible,
(CFDataRef)itemData, kSecValueData,
nil];
OSStatus updateItemStatus = SecItemUpdate((CFDictionaryRef)query,
(CFDictionaryRef)updatedAttributes);
// updateItemStatus should have the value errSecSuccess
答案 1 :(得分:1)
我无法得到另一个工作的答案。我最终测试了kSecAttrAccessibile,如果它不是我想要的,我在局部变量的keychain中记录了值和属性,重置了keychain,根据需要设置了kSecAttrAccessible,然后将keychain中的值和属性设置为原始设置。