iOS8 + KeychainItemWrapper от Apple приводит к сбою
Я копался в форумах Apple и ТАК для этой проблемы, но безрезультатно. Используя Apple KeychainItemWrapper (ARCified), пытаясь установить kSecAttrAccessible
приписывать что-либо, кроме по умолчанию (kSecAttrAccessibleWhenUnlocked
) приводит к ошибке подтверждения из SecItemUpdate, возвращающей ошибку.
KeychainItemWrapper *wrapper = [[KeyChainItemWrapper alloc] initWithIdentifier:kMyIdentifier accessGroup:nil];
[wrapper setObject:kMyServiceName forKey:(__bridge NSString*)kSecAttrService];
[wrapper setObject:kMyAccountToken forKey:(__bridge NSString*)kSecAttrAccount];
[wrapper setObject:(__bridge NSString*)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly forKey:(__bridge NSString*)kSecAttrAccessible];
Остальные наши обновления цепочки для ключей, кажется, проходят хорошо, но последняя строка приводит к:
*** Assertion failure in -[KeychainItemWrapper writeToKeychain], /Users/john.hammerlund/.../KeychainItemWrapper.m:299
Ошибка подтверждения связана с тем, что SecItemUpdate() возвращает состояние -50, что, по-видимому, является общей ошибкой "неверных параметров".
Сразу установка kSecAttrAccessible
ключ не влияет, но установка его по умолчанию kSecAttrAccessibleWhenUnlocked
смягчает проблему (но устраняет суть). Этот другой вопрос - единственная дополнительная информация, которую я нашел относительно iOS 8, вызывающей сбой KeychainItemWrapper. Построение на устройстве с iOS 7 или симулятор на iOS 7/8 устраняет проблему; он вспыхивает только на реальном устройстве с iOS 8.
Обновить
Вот широкий обзор словаря запросов:
{
accc = "<SecAccessControlRef: 0x1687cc70>";
acct = ...;
agrp = ...;
cdat = "2014-10-13 22:22:47 +0000";
desc = "";
gena = ...;
labl = "";
mdat = "2014-10-13 22:34:16 +0000";
pdmn = cku; <-- kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
svce = ...;
sync = 0;
tomb = 0;
"v_Data" = <>;
}
и параметр attributeToUpdate:
{
accc = "<SecAccessControlRef: 0x1687cc70>";
acct = ...;
agrp = ...;
cdat = "2014-10-13 22:22:47 +0000";
desc = "";
gena = ...;
labl = "";
mdat = "2014-10-13 22:34:16 +0000";
pdmn = ak; <-- kSecAttrAccessibleWhenUnlocked
svce = ...;
sync = 0;
tomb = 0;
"v_Data" = <>;
}
Я подтвердил, что изменение других полей (например, kSecAttrService, kSecAttrAccount) одинаково влияет на соответствующие поля в словарях, но с ожидаемым состоянием 0.
3 ответа
У меня тоже была точная проблема. Дал мне:
Ошибка OSStatus -50 - конфликтующие атрибуты kSecAccess и kSecAccessControl
Сбой всем моим пользователям в магазине приложений сразу после их обновления.
Сделал так же, как Петр. Схватил данные, удалил элемент и вставил его как новый элемент вместо попытки обновить существующий.
Я думаю, это ошибка Apple.
Я открыл TSI, но они еще не связались со мной.
Насколько я понимаю, это происходит с пользователями, обновленными с iOS7 до iOS 8, где их первое приложение было скомпилировано с XCode для iOS7 (до выхода iOS 8), а затем на iOS8 обновлено до нового приложения, скомпилированного с XCode для iOS8,
У меня такая же проблема. Я закончил тестированием kSecAttrAccessibile и, если это было не то, что я хотел, я записал значение и атрибуты в цепочку для ключей в локальных переменных, сбросил цепочку для ключей, установил kSecAttrAccessible по желанию, а затем установил значение и атрибуты в цепочке для ключей в их исходные настройки.
Выстрел в темноте здесь:
Возможно, на устройстве iOS включена синхронизация iCloud, добавление элемента, который не зависит от конкретного устройства, а затем его создание ThisDeviceOnly приводит к ошибке. iOS8, возможно, также изменил поведение.
Можете ли вы попробовать изменить порядок атрибутов, которые установлены в связку ключей
KeychainItemWrapper *wrapper = [[KeyChainItemWrapper alloc] initWithIdentifier:kMyIdentifier accessGroup:nil];
[wrapper setObject:(__bridge NSString*)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly forKey:(__bridge NSString*)kSecAttrAccessible];
[wrapper setObject:kMyServiceName forKey:(__bridge NSString*)kSecAttrService];
[wrapper setObject:kMyAccountToken forKey:(__bridge NSString*)kSecAttrAccount];
Если это не помогает, вы должны изменить KeychainItemWrapper, чтобы выглядеть так
- (void)resetKeychainItem
{
if (!keychainItemData)
{
keychainItemData = [[NSMutableDictionary alloc] init];
[keychainItemData setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly forKey:(__bridge id)kSecAttrAccessible];
}