2011-03-20 101 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

相關問題