Подтвердить что ты не робот

Возможно ли обновить значение KeyShain kSecAttrAccessible?

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

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

4b9b3361

Ответ 1

После открытия поддержки в технической поддержке Apple Developer (ADTS), я получил ответ, который отвечает на этот вопрос. SecItemUpdate() требует данных элемента Keychain через атрибут kSecValueData для выполнения обновления атрибута kSecAttrAccessible. Согласно ADTS, это ограничение в настоящее время не зарегистрировано в справочной документации.

NSData *encodedIdentifier = [@"BUNDLE_IDENTIFIER" 
                             dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
                       kSecClassGenericPassword, kSecClass,
                       encodedIdentifier, kSecAttrGeneric,
                       encodedIdentifier, kSecAttrService,
                       nil];

// Obtain the Keychain item 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

Ответ 2

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