2011-03-20 76 views
19

是否可以更新钥匙串中现有项目的属性kSecAttrAccessible的值?看起来,该项目添加到钥匙串后无法更改。以下步骤备份我的假设。从kSecAttrAccessibleWhenUnlocked是否有可能更新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); 

在以后的时间,改变属性kSecAttrAccessiblekSecAttrAccessibleAfterFirstUnlock

添加新项钥匙扣

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的值,因为应用程序的要求发生了变化。如果应用程序过去在钥匙串中添加了10个项目而没有用kSecAttrAccessible指定保护等级,该怎么办?如果开发人员未明确设置保护类别,则钥匙串将隐式分配新项目kSecAttrAccessibleWhenUnlocked。之后,开发人员需要将保护类更改为kSecAttrAccessibleAfterFirstUnlock,因为应用程序必须在后台访问它(多任务处理)。开发人员如何实现这一目标?

目前已经在苹果开发者论坛一个线程,但它并没有得到一个答案了:https://devforums.apple.com/thread/87646?tstart=0

回答

18

在苹果开发者技术支持(ADTS)打开支持事件后,我收到了回答这个答复题。 SecItemUpdate()需要钥匙串项目的数据通过属性kSecValueData执行属性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

现在[记录](https://developer.apple.com/library/ios/documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/c/data/kSecAttrAccessible)为在iOS 4及更早版本中需要。 – 2013-09-16 15:52:22

+0

好找!谢谢。 – mbinna 2013-09-17 07:42:07

+0

如果您使用RSA密钥对,请确保为* both *键执行此操作。 – 2017-07-22 00:29:06

1

我无法得到其他答案的工作。我最终测试了kSecAttrAccessibile,如果它不是我想要的,我在本地变量中记录了钥匙串中的值和属性,重置钥匙串,根据需要设置kSecAttrAccessible,然后将钥匙串中的值和属性设置为其原始设置。

+0

你不会碰巧有这样的代码片段吗?无法正常工作 – 2017-07-24 15:45:11

相关问题