Выдать сертификат сохранения на связку ключей iOS -25300 (не найден) при удалении, но -25299 (дубликат) при добавлении - PullRequest
2 голосов
/ 02 октября 2019

У меня возникла интересная проблема с цепочкой ключей Apple, и мне интересно, что я делаю неправильно.

    func saveCert(accessGroup: String? = nil, certData: Data, label: String? = nil) -> Error? {
        var query = createKeychainAddQueryDict()
        if let accessGroup = accessGroup {
            query[String(kSecAttrAccessGroup)] = accessGroup
        }

        query[String(kSecValueData)] = certData
        query[String(kSecClass)] = kSecClassCertificate

        if let label = label {
            query[String(kSecAttrLabel)] = label
        }

        var status = SecItemDelete(query as CFDictionary)
        if status != noErr {
            print("Error deleting cer from keychain. Error: \(status)")
        }

        let resultCode = SecItemAdd(query as CFDictionary, nil)
        return getErrorFromKeychainCode(code: resultCode)
    }

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

Я получаю ошибку -25300 (не могу найти элемент), когда пытаюсь удалить сертификат, но я получаю ошибку -25299 (повторяющийся элемент уже существует), когда я пытаюсь сохранить ее в цепочке для ключей.

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

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

Ответы [ 2 ]

1 голос
/ 02 октября 2019

Я нашел два решения:

  1. Запрос значений для определенного ключа позже. Использовать асинхронную задержку. Время от времени брелок не дает результат с -25300. Брелок тоже является базой данных SQLite. Кажется, база данных в настоящее время занята. Итак, запросите данные позже.
  2. Вы уже что-то записали в этот ключ, но использовали другой уровень защиты. Чтобы избежать этого, используйте ключи с уровнем защиты внутри своего имени. Например, someKey в someKey-afterFirstUnlock
0 голосов
/ 03 октября 2019

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

Поскольку я использую самоподписанный сертификат, операция SecCertificateCreateWithData завершается неудачно с результатом nil. Я полагаю, что это приводит к тому, что все мои сертификаты оцениваются по одному и тому же пусто-пустому идентификатору. Я попытался сохранить эти же данные в kSecGenericPassword и установить отдельный атрибут учетной записи, и проблема исчезла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...