使用Secure Enclave iOS AES-GCM进行加密/解密

时间:2019-05-28 07:43:13

标签: ios encryption swift4 aes aes-gcm

我在iOS上使用SecureEnclave加密/解密我的机密密钥,并将其保存在UserPreferences中。它已被设置并成功加密数据。但是,每当我尝试解密数据时,都会出现以下错误:

  

Error Domain = NSOSStatusErrorDomain代码= -50 \“ ECIES:无法对es-gcm解密数据\” UserInfo = {NSDescription = ECIES:不能对es-gcm解密数据}

经过大量搜索,我发现了一些链接,但它们没有任何帮助。 This Github issue讨论了这个问题。它说,

  

此外,在10.3上,使用kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM解密大量数据时出现问题。我为此提交了一个错误报告,此问题已在iOS 11中修复。:)

但是我将iPhone 8与iOS 12.2配合使用,仍然存在问题。

这两个SO问题herehere提供了一些细节,但我无法对其进行解读。另外,我正在使用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 个答案:

答案 0 :(得分:1)

我遇到了同样的错误,发现我生成了两个不同的密钥对,在其中我用一个公共密钥加密了数据,但又使用了另一个错误的私有密钥进行了解密。因此,请确保解密操作使用与加密中使用的公钥相对应的正确私钥。