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

标签 ios encryption swift4 aes aes-gcm

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

Error Domain=NSOSStatusErrorDomain Code=-50 \"ECIES: Failed to aes-gcm decrypt data\" UserInfo={NSDescription=ECIES: Failed to aes-gcm decrypt data}

经过大量搜索,我找到了一些链接,但它们没有任何帮助。 This Github issue谈论这个问题。它指出,

Additionally, on 10.3 there was a problem with decrypting large amounts of data with kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM. I filed a bug report for it, and it got fixed in iOS 11. :)

但我使用的是 iPhone 8 和 iOS 12.2,但仍然存在问题。

这两个SO问题,herehere提供一些细节,但我无法破译它。另外,我使用的是 Swift 4。

下面是我用来加密/解密数据的相关代码。

生成 key 对

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
}

非常感谢任何帮助。谢谢。

最佳答案

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

关于ios - 使用 Secure Enclave iOS AES-GCM 加密/解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56337291/

相关文章:

ios - 无法在旧项目上运行 UI 测试

react-native - 在react-native中使用加密数据库

ios - 如何在 swift 3 或 4 中创建像 apple app installer 这样的循环进度条

ios - 使用 Swift 为所有 UIViewControllers 实现功能

ios - RKObjectMapping 和 RKEntityMapping 的关系

ios - 重置 UIProgressView 并立即开始动画

security - 向后 HTTPS;用户与之前生成的私钥进行通信

Javascript - 使用密码加密数据的最佳方式

ios - swift4:关闭当前 View Controller 并显示另一个没有 navigationController 的 Controller

ios - UICollectionView.backgroundView 损坏