Можно ли обновить значение kSecAttrAccessible элемента цепочки для ключей? - PullRequest
21 голосов
/ 20 марта 2011

Можно ли обновить значение атрибута 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, потому что требования приложений меняются.Что если в прошлом приложение добавляло десять элементов в связку ключей без указания класса защиты с помощью kSecAttrAccessible.Цепочка для ключей неявно присваивает новым элементам значение kSecAttrAccessibleWhenUnlocked, если класс защиты не установлен явным образом разработчиком.Позднее разработчику необходимо изменить класс защиты на kSecAttrAccessibleAfterFirstUnlock, поскольку приложение должно обращаться к нему в фоновом режиме (многозадачность).Как разработчик может сделать это?

В форумах разработчиков Apple уже есть тема, но она еще не дала ответа: https://devforums.apple.com/thread/87646?tstart=0

Ответы [ 2 ]

19 голосов
/ 14 апреля 2011

После открытия инцидента в Службе технической поддержки Apple Developer (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 голос
/ 27 ноября 2014

Мне не удалось получить другой ответ на работу. Я закончил тестированием kSecAttrAccessibile и, если это было не то, что я хотел, я записал значение и атрибуты в цепочку для ключей в локальных переменных, сбросил цепочку для ключей, установил kSecAttrAccessible по желанию, а затем установил значение и атрибуты в цепочке для ключей в их исходные настройки.

...