使用 SecKeyGeneratePair 在 iOS 中生成密钥对失败,错误为 errSecInteractionNotAllowed

Generating key pair in iOS using SecKeyGeneratePair failed with errSecInteractionNotAllowed

在我的应用程序中,我使用 SecKeyGeneratePair 生成 RSA 密钥对。发布该应用程序后,我开始注意到在使用此功能时偶尔出现 errSecInteractionNotAllowed 错误(目前非常罕见),到目前为止仅在 iOS 10 台设备上出现。我不清楚为什么密钥对生成失败,或者我应该如何解决这个问题。此外,我找不到任何文档说明为什么密钥对生成会因此错误而失败。

这是我用来生成密钥对的代码:

guard let access = SecAccessControlCreateWithFlags(nil,
                                                       kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
                                                       [],
                                                       nil) else {throw Error(description: "Failed to create access control")}

    let privateAttributes = [String(kSecAttrIsPermanent): true,
                             String(kSecAttrApplicationTag): keyTag + self.privateKeyExtension,
                             String(kSecAttrAccessControl): access] as [String : Any]
    let publicAttributes = [String(kSecAttrIsPermanent): true,
                            String(kSecAttrApplicationTag): keyTag + self.publicKeyExtension] as [String : Any]

    let pairAttributes = [String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
                          String(kSecAttrKeySizeInBits): self.rsaKeySize,
                          String(kSecPublicKeyAttrs): publicAttributes,
                          String(kSecPrivateKeyAttrs): privateAttributes] as [String : Any]
    var pubKey, privKey: SecKey?
    let status = SecKeyGeneratePair(pairAttributes as CFDictionary, &pubKey, &privKey)

在这段代码之后,我正在检查状态,如果不是 errSecSuccess,我会记录一个错误,并显示函数返回的状态。这是我注意到 errSecInteractionNotAllowed 错误的地方。 那么,为什么会生成密钥对或者我可以做些什么来修复它?

谢谢,

奥马尔

两条建议:

  1. 尝试为您的 SecAccessControlCreateWithFlags 调用添加其他保护 class,例如 kSecAttrAccessibleAlways,并测试该行为是否仍然发生。
  2. 进一步定义一个flag for your use case instead of passing an empty array. E.g. userPresence.

另外我偶然发现了这个SO post,也许你可以在那里找到一些灵感。

与 Apple Developer Support 讨论后,这里是解决方案:

 let privateAttributes = [String(kSecAttrIsPermanent): true,
                                 String(kSecAttrApplicationTag): keyTag + self.privateKeyExtension,
                                 String(kSecAttrAccessible): kSecAttrAccessibleAlways] as [String : Any]
        let publicAttributes = [String(kSecAttrIsPermanent): true,
                                String(kSecAttrApplicationTag): keyTag + self.publicKeyExtension,
                                String(kSecAttrAccessible): kSecAttrAccessibleAlways] as [String : Any]

        let pairAttributes = [String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
                              String(kSecAttrKeySizeInBits): self.rsaKeySize,
                              String(kSecPublicKeyAttrs): publicAttributes,
                              String(kSecPrivateKeyAttrs): privateAttributes] as [String : Any]
        var pubKey, privKey: SecKey?
        let status = SecKeyGeneratePair(pairAttributes as CFDictionary, &pubKey, &privKey)

重要的部分是 kSecAttrAccessible,从中选择符合您需要的值 list。请注意,某些值将限制对 KeyVault 中密钥的访问。