Шифрование / дешифрование с использованием Secure Enclave iOS AES-GCM - PullRequest
2 голосов
/ 28 мая 2019

Я использую SecureEnclave на iOS для шифрования / дешифрования моего секретного ключа и сохранения его в UserPreferences. Он был успешно настроен и зашифрован. Но всякий раз, когда я пытаюсь расшифровать данные, я получаю следующую ошибку:

Ошибка домена = NSOSStatusErrorDomain Code = -50 \ "ECIES: не удалось расшифровать данные aes-gcm \" UserInfo = {NSDescription = ECIES: не удалось расшифровать данные aes-gcm}

После долгих поисков я нашел несколько ссылок, но они не помогают. Эта проблема Github говорит о проблеме. В нем говорится,

Кроме того, в 10.3 возникла проблема с расшифровкой больших объемов данных с помощью kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM. Я подал отчет об ошибке, и это было исправлено в iOS 11. :)

Но я использую iPhone 8 с iOS 12.2, и проблема все еще существует.

Эти два вопроса SO, здесь и здесь предоставляют некоторые детали, но я не могу их расшифровать. Плюс я пользуюсь Swift 4.

Ниже приведен соответствующий код, который я использую для шифрования / дешифрования данных.

Для создания пары ключей

func generateKeyPair(accessControl: SecAccessControl) throws -> (`public`: SecureEnclaveKeyReference, `private`: SecureEnclaveKeyReference) {

    let publicKeyParameters: [String: AnyObject] = [
        kSecAttrIsPermanent as String: false as AnyObject,
        kSecAttrApplicationTag as String: "com.xxx.xxx" as AnyObject,
        kSecAttrLabel as String: "PublicKey" as AnyObject
    ]

    let privateKeyParameters: [String: AnyObject] = [
        (kSecAttrCanDecrypt as CFString) as String: true as CFBoolean,
        kSecAttrIsPermanent as String: true as AnyObject,
        kSecAttrAccessControl as String: accessControl,
        kSecAttrApplicationTag as String: "com.xxx.xxx" as AnyObject,
        kSecAttrLabel as String: "PrivateKey" as AnyObject
    ]

    let parameters: [String: AnyObject] = [
        kSecAttrKeyType as String: kSecAttrKeyTypeEC,
        kSecAttrKeySizeInBits as String: 256 as AnyObject,
        kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
        kSecPublicKeyAttrs as String: publicKeyParameters as AnyObject,
        kSecPrivateKeyAttrs as String: privateKeyParameters as AnyObject
    ]



    var publicKey, privateKey: SecKey?
    let status = SecKeyGeneratePair(parameters as CFDictionary, &publicKey, &privateKey)

    print("Result = \(status) - Public Key = \(publicKey) - Private Key = \(privateKey)")


    guard status == errSecSuccess else {

        throw SecureEnclaveHelperError(message: "Could not generate keypair", osStatus: status)
    }


    return (public: SecureEnclaveKeyReference(publicKey!), private: SecureEnclaveKeyReference(privateKey!))

}

Шифрование

@available(iOS 10.3, *)
func encrypt(_ digest: Data, publicKey: SecureEnclaveKeyReference) throws -> Data {

    var error : Unmanaged<CFError>?

    let result = SecKeyCreateEncryptedData(publicKey.underlying, SecKeyAlgorithm.eciesEncryptionStandardX963SHA256AESGCM, digest as CFData, &error)

    if result == nil {

        throw SecureEnclaveHelperError(message: "\(error)", osStatus: 0)
    }

    return result as! Data
}

дешифрование

@available(iOS 10.3, *)
func decrypt(_ digest: Data, privateKey: SecureEnclaveKeyReference) throws -> Data {

    var error : Unmanaged<CFError>?

    let result = SecKeyCreateDecryptedData(privateKey.underlying, SecKeyAlgorithm.eciesEncryptionStandardX963SHA256AESGCM, digest as CFData, &error)

    if result == nil {

        throw SecureEnclaveHelperError(message: "\(error)", osStatus: 0)
    }

    return result as! Data
}

Любая помощь высоко ценится. Спасибо.

1 Ответ

1 голос
/ 31 мая 2019

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

...