SecItemAdd и SecItemCopyMatching возвращают код ошибки -34018 (errSecMissingEntitlement)

Иногда, когда я запускаю приложение на устройстве из Xcode, я пытаюсь получить доступ к цепочке ключей, но сбой из-за ошибки -34018. Это не соответствует ни одному из документированных кодов ошибок в цепочке ключей и не может быть последовательно воспроизведено. (может быть, 30% времени, и мне непонятно, почему это происходит). Что очень затрудняет отладку этой проблемы, так это полная нехватка документации. Любая идея, что вызывает это и как его исправить? Я использую Xcode 5 и запускаю iOS 7.0.4 на устройстве.

Существует открытая проблема об этом здесь: https://github.com/soffes/sskeychain/issues/52

EDIT: добавление кода доступа к цепочке ключей для каждого запроса

Я использую библиотеку SSKeychain для взаимодействия с keychain. Вот фрагмент.

#define SERVICE @"default"

@implementation SSKeychain (EXT)

+ (void)setValue:(NSString *)value forKey:(NSString *)key {
    NSError *error = nil;
    BOOL success = NO;
    if (value) {
        success = [self setPassword:value forService:SERVICE account:key error:&error];
    } else {
        success = [self deletePasswordForService:SERVICE account:key error:&error];
    }
    NSAssert(success, @"Unable to set keychain value %@ for key %@ error %@", value, key, error);
    if (!success) {
        LogError(@"Unable to set value to keychain %@", error);
    }
    LogTrace(@"Will set keychain account %@. is to nil? %d", key, value == nil);
    if (value == nil)
        LogWarn(@"Setting keychain %@ to nil!!!", key);
}

+ (NSString *)valueForKey:(NSString *)key {
    NSError *error = nil;
    NSString *value = [self passwordForService:SERVICE account:key error:&error];
    if (error && error.code != errSecItemNotFound) {
        NSAssert(!error, @"Unable to retrieve keychain value for key %@ error %@", key, error);
        LogError(@"Unable to retrieve keychain value for key %@ error %@", key, error);
    }
    return value;
}

+ (BOOL)removeAllValues {
    LogInfo(@"Completely Reseting Keychain");
    return [[self accountsForService:SERVICE] all:^BOOL(NSDictionary *accountInfo) {
        return [self deletePasswordForService:SERVICE account:accountInfo[@"acct"]];
    }];
}

@end

В большинстве случаев это просто отлично. Иногда я ударяю ошибки утверждения, когда я не могу ни писать, ни читать из брелка, вызывая критический отказ от утверждения.

Ответ 1

iOS 10/XCode 8 Fix:

Добавить право KeyChain, перейти к проекту settings- > Capabilities- > Keychain Sharing- > Добавить группы ключей + Включить

Ответ здесь, от Apple:

UPDATE: наконец, мы смогли воспроизвести ошибку -34018 на iOS 8.3. Это первый шаг в определении основной причины, а затем придумывание исправления.

Как обычно, мы не можем зафиксировать таймфрейм выпуска, но это затронуло многих разработчиков, и мы действительно хотим, чтобы это разрешилось.

Ранее я предложил добавить небольшую задержку в application: didFinishLaunchingWithOptions и applicationDidBecomeActive: перед доступом к цепочке ключей как обходной путь. Однако это фактически не помогает. Это значит что в это время нет известного обходного пути, кроме возобновления приложение.

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

https://forums.developer.apple.com/thread/4743#14441

ОБНОВЛЕНИЕ

Хорошо, это последнее.
Это сложная проблема с несколькими возможные причины:

  • Некоторые примеры проблемы вызваны неправильным подписка на приложение. Вы можете легко отличить этот случай, потому что проблема на 100% воспроизводимо.
  • Некоторые примеры проблемы вызваны ошибка в том, как iOS поддерживает разработку приложений (23,991,853). отладка это осложнялось тем, что другая ошибка в ОС (т. 23,770,418) замаскировал его эффект, что означает, что проблема только возникла когда устройство находилось под давлением памяти. Мы считаем, что эти проблемы были решены в IOS 9.3.
  • Мы подозреваем, что может быть еще больше причин этой проблемы.

Итак, если вы видите эту проблему на пользовательском устройстве (один с которым Xcode не разговаривал), который работает под управлением iOS 9.3 или новее, пожалуйста, сообщите об этом об ошибке. Попробуйте включить устройство система регистрирует ваш отчет об ошибках (я понимаю, что может быть сложно, когда работа с клиентскими устройствами; один из вариантов - попросить клиента установите Apple Configurator, который позволяет просматривать системный журнал). А также если вы делаете ошибку, отправьте свой номер ошибки, только для запись.

От имени Apple Id нравится благодарить всех за их усилия по поиску этой довольно ужасной проблемы. Доля и Наслаждайтесь

https://forums.developer.apple.com/thread/4743#126088

Ответ 2

В основном вы должны координировать свою папку .xcttest, добавив следующее в качестве запуска script в тестовую цель.

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

У меня было много ошибок -34018 при тестировании моей брелка на устройстве, и это удалось исправить.

Если проблема не существует в вашей тестовой цели, это, вероятно, не решение.

Ответ 3

После проверки исходного кода. Я заметил, что функции keychain доступны через демона безопасности, который работает в своем собственном процессе (отделенный от процесса приложения).

Ваше приложение и процесс обеспечения безопасности "разговаривают" вместе с помощью технологии XPC.

Если необходимо, securityd запускается через известную команду launchd от XPC. Вероятно, вы можете проверить, что демон запущен в приложении Activity Monitor (если он работает в Simulator, конечно) и что его родительский процесс запускается.

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

Возможно, вы могли бы подумать о том, как предварительно запустить демон.

Я извиняюсь за то, что не уточнил. Надеюсь, это поможет вам укусить в ваших расследованиях.

Ответ 4

Im наблюдает подобное поведение после создания и запуска моего кода в бета-версии Xcode 6 с помощью SDK iOS 8 (он корректно работает с Xcode 5/iOS 7). В Xcode 6 в iOS Simulator SecItemCopyMatching всегда возвращает -34018. Он начал работать после включения вкладки "Совместное использование брелка" на вкладках "Возможности".

Однако у меня есть еще одна проблема. Im разрабатывает статическую библиотеку, которая используется (среди прочих) демонстрационным приложением. Вышеупомянутое решение работает для проекта Demo application, но когда я пытаюсь выполнить unit test мой проект статической библиотеки, у меня точно такая же ошибка. И проблема в том, что у моего проекта статической библиотеки нет вкладки "Возможности" (как ее не отдельного приложения).

Ive попробовал решение, размещенное здесь JorgeDeCorte, с кодовым именем в тестовом объекте, но оно не работает для меня.

Ответ 5

Попробуйте отключить все точки останова при запуске приложения из Xcode. Вы можете включить их позже.

(Ни один из вышеперечисленных методов работы не работал у меня)

Ответ 6

У меня была такая же проблема на симуляторе, работающем на 7.1 и 8.0. Делая некоторое копание, я заметил, что в образцовом приложении Apple был включен KeyChain Sharing для его целевых возможностей. Я включил его для своего приложения, которое привело к созданию файла права, который я оставил со значениями по умолчанию, и теперь я больше не получаю ошибок -34018. Это не идеально, но сейчас я буду использовать параметр совместного доступа KeyChain.

Ответ 7

Я тоже укусил это и не имел успеха ни с одним из обходных решений. Затем я очистил свои профили настройки на самих устройствах, удалив все из них, связанных с моим приложением, а также все профили подстановочных знаков (это, похоже, точка). Для этого перейдите в окно "Устройства" в Xcode и щелкните правой кнопкой мыши ваш (подключенный) телефон:

Нажмите "Показать профили настройки" и удалите связанные с ними, и особенно профили команд:

включая те, у которых есть звездочка. После переустановки приложения все вернулось к нормальной жизни.

Ответ 8

Кодирование .xctest-пакета не так просто, как кажется в некоторых случаях. В принципе JorgeDeCorte прав с ответом , что данной короткой строки как Run Script достаточно для большинства разработчиков.

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

Но когда у вас есть несколько сертификатов в вашей цепочке ключей, это приведет к сбою со следующей строкой

iPhone Developer: ambiguous (matches "iPhone Developer: Your Name (ABC123DEF45)" and "iPhone Developer: Your Name (123ABC456DE)"

Решение получить правильный сертификат даже с несколькими из них - это короткий script. Конечно, это не идеально, но, насколько мне известно, у вас нет шансов получить сертификат, который Xcode нашел и использует для подписания вашего .app.

echo "codesign --verify --force --sign \"$CODE_SIGN_IDENTITY\" \"$CODESIGNING_FOLDER_PATH\""
IDENTITIES=`security find-identity -v -s "Code Signing" | grep "iPhone Developer" | awk '{ print $2 }'`

for SHA in $IDENTITIES; do
    codesign --verify --force --sign $SHA "$CODESIGNING_FOLDER_PATH"
    if [ $? -eq 0 ]; then
        echo "Matching identity found: $SHA"
        exit 0
    fi
done;

exit 1

Ответ 9

Я исправил эту проблему (думаю). На моем устройстве у меня был профиль настройки подстановочного знака, который показал, что у него нет действительного идентификатора подписи. У меня также был профиль обеспечения для моего приложения, которое было действительно. Когда я удалил профиль подстановки, я прекратил получать ошибки -34018.

Я также удостоверился, что идентификатор идентификации и профилирования кода, указанный в разделе "Подписание кода" в настройках сборки целевого объекта, был идентичен идентификатору приложения (а не общему "Разработчику iPhone" )

Ответ 10

Я редко получал ошибку -34018 в моем приложении (iOS 8.4). После некоторого расследования я обнаружил, что эта проблема возникает, когда приложение запрашивает данные из связки ключей слишком часто.
Например, в моей ситуации это два запроса на чтение для одного конкретного ключа одновременно с различными модулями приложения.
Чтобы исправить это, я только что добавил кеширование этого значения в памяти

Ответ 11

У меня была одна и та же проблема, совершенно неожиданно, на тестовом устройстве с Xcode 6.2, iPhone 6, iOS 8.3. Чтобы быть ясным, это не было выполнено во время выполнения тестов Xcode, но, скорее, при запуске фактического приложения на моем устройстве. В симуляторе это было прекрасно, и, работая на самом приложении, до недавнего времени все было в порядке.

Я попробовал все предложения, которые я мог найти здесь, например удаление профилей подготовки на моем устройстве (я удалил их все), временно включив возможность совместного использования ключей в моем проекте (хотя нам это действительно не нужно), убедившись, что моя учетная запись разработки в Xcode была полностью обновлена ​​со всеми сертификатами и профилями профилей и т.д. Ничего не помогло.

Затем я временно изменил уровень доступности с kSecAttrAccessibleAfterFirstUnlock на kSecAttrAccessibleAlwaysThisDeviceOnly, запустил приложение, и он отлично работал и смог записать в цепочку ключей. Затем я изменил его на kSecAttrAccessibleAfterFirstUnlock, и проблема, похоже, исчезла "навсегда".

Ответ 12

Просто укушен этой ошибкой в ​​Xcode 8 Beta 3. Включение совместного использования ключей - единственное решение.

Ответ 13

У меня была такая же проблема. Исправлено это путем настройки совместного использования ключей.

Ответ 14

(это не прямой ответ на вопрос OP, но может помочь другим)

Начнется получение ошибки keychain -34018 последовательно в симуляторе после обновления Xcode с версии 7.3.1 до 8.0.

Следуя этому совету из ответа daidai,

Некоторые примеры проблемы вызваны неправильной подпиской на приложение. Вы можете легко отличить этот случай, потому что проблема на 100% воспроизводима.

было обнаружено, что профиль Provisioning Profile каким-то образом был установлен на None в разделах Signing цели.

Однако установка полей профиля Provisioning для допустимых значений была недостаточной для решения проблемы в этом случае.

Дальнейшие исследования показали, что право на Push Push также показало ошибку. Он сказал, что "Добавить функцию Push Notifications в ваш идентификатор приложения". шаг был завершен, но шаг "Добавить права Push Notifications в ваш файл прав" не был.

После нажатия кнопки "Исправить проблему", чтобы устранить проблему с Push Notification, проблема с цепочкой ключей была устранена.

Для этой конкретной цели право "Доступ к связям с ключами" уже было включено в предыдущее время. Отключение его не привело к тому, что ошибка keychain снова появилась, поэтому неясно, необходимо ли в этом случае.

Ответ 15

В iOS 9 я отключил Address Sanitizer и начал работать с устройством.

Ответ 16

Единственное решение, которое сработало для меня, - это сначала сохранить nil для указанного ключа, а затем сохранить новое значение с помощью отдельной операции. Он не сработает из-за ошибки -34018, если я попытаюсь перезаписать существующее значение. Но до тех пор, пока я сначала сохранил nil, обновленное значение будет сохранено сразу же после этого.

Ответ 17

Сегодня я столкнулся с этой проблемой -34018 при запуске SecItemDelete API. Что я сделал, чтобы исправить это: 1. Следуя @k1th решению fooobar.com/questions/50977/... 2. Запустите SecItemDelete в основном потоке (ранее он читается из основного потока, поэтому просто выровняйте его с удалением).

Извините, он возвращается снова: (

Ответ 18

Включите совместное использование брелка в своих возможностях проекта, он должен решить проблему. введите описание изображения здесь

Ответ 19

Что сработало для меня

  • Включить брелок для обмена.
  • Используйте как можно меньше цепочку для ключей и кэшируйте данные в памяти, пользовательских настройках, диске и т.д.
  • Повторите много раз операции CRUD цепочки для ключей, если они потерпели неудачу.
  • Используйте DispatchQueue.sync для хранения/удаления/обновления данных.

Ответ 20

Для меня это была проблема с подписью приложений. Я просто переключился на правильную команду подписи в XCode, и ошибка больше не произошла