ios - 使用私钥和 TouchID 或 FaceID swift 对消息进行签名

标签 ios swift rsa signature touch-id

我已使用 SecKeyCreateRandomKey 在钥匙串(keychain)中创建了私钥。当我尝试访问 key 以执行签名操作时,Touch ID 或 FaceID 对话框永远不会出现。我得到了符号字符串,但没有 TouchID 或 FaceID。我尝试使用 BiometryAnyTouchIdAny 但它不起作用。

static func createKey(keyName:String){
    DispatchQueue.main.async{
    var error : Unmanaged<CFError>?
    print("Key is generating for \(keyName)")
    let tag = (keyName + "PrivateKey").data(using: .utf8)!
    // private key parameters
    var privateKeyParams: [String: Any] = [:]
    let accessControlError:UnsafeMutablePointer<Unmanaged<CFError>?>? = nil
    // ^ Already a 'pointer'
    if #available(iOS 10 , *) {
        let allocator:CFAllocator!         = kCFAllocatorDefault
        let protection:AnyObject!             = kSecAttrAccessibleWhenUnlockedThisDeviceOnly

        let flags:SecAccessControlCreateFlags = SecAccessControlCreateFlags.userPresence
        let accessControlRef = SecAccessControlCreateWithFlags(
            allocator,
            protection,
            flags,
            accessControlError // <- Notice the lack of '&'
        )
        privateKeyParams = [
            kSecAttrIsPermanent as String: true,
            kSecAttrApplicationTag as String: tag,
            kSecAttrAccessControl as String : accessControlRef!,
        ]
    } else {

        // Fallback on earlier versions
    }


    // global parameters for our key generation
    let parameters: [String: Any] = [
        kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
        kSecAttrKeySizeInBits as String: 2048,

        kSecPrivateKeyAttrs as String: privateKeyParams
    ]
     if #available(iOS 10.0, *) {
        do{
            guard let privateKey = SecKeyCreateRandomKey(parameters as CFDictionary, nil) else {
                print("\(keyName)PrivateKey generator Error!")
                throw error!.takeRetainedValue() as Error
            }
          }
       }
    }

和签名函数:

static func SigntureWithPrivateKey(keyName: String, message : String) -> String {
    //print("sign started .........")
    guard let messageData = message.data(using: String.Encoding.utf8) else {
            print("bad message to sign")
            return ""
    }
    if #available(iOS 10.0, *) {
        guard let privateKeyLocal: SecKey = getPrivateKey("\(keyName)PrivateKey") else
        {
            return ""
        }
        guard let signData = SecKeyCreateSignature(privateKeyLocal,SecKeyAlgorithm.rsaSignatureDigestPKCS1v15SHA512,messageData as CFData, nil) else {
            print("priv ECC error signing")
            return ""
        }
        let convertedSignData = signData as Data
        let convertedString = convertedSignData.base64EncodedString()
        return convertedString

    } else {
        return ""
    }


}

和 getPrivateKey 函数:

fileprivate static func getPrivateKey(_ name: String) -> SecKey?
{
    let query: [String: Any] = [
        kSecClass as String: kSecClassKey,
        kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
        kSecAttrApplicationTag as String: name,
        kSecReturnRef as String: true
    ]

    var item: CFTypeRef? = nil
    let status = SecItemCopyMatching(query as CFDictionary, &item)

    guard status == errSecSuccess else
    {
        if status == errSecUserCanceled
        {
            print("\tError: Accessing private key failed: The user cancelled (%@).", "\(status)")
        }
        else if status == errSecDuplicateItem
        {
            print("\tError: The specified item already exists in the keychain (%@).", "\(status)")
        }
        else if status == errSecItemNotFound
        {
            print("\tError: The specified item could not be found in the keychain (%@).", "\(status)")
        }
        else if status == errSecInvalidItemRef
        {
            print("\tError: The specified item is no longer valid. It may have been deleted from the keychain (%@).", "\(status)")
        }
        else
        {
            print("\tError: Accessing private key failed (%@).", "\(status)")
        }
        return nil
    }

    return (item as! SecKey)
}

最佳答案

抱歉,您的问题很长,所以我想我会给出通用答案。

  • 确保您已在您的 信息.plist

    如果没有此 key ,系统将不允许您的应用使用 Face ID。这 该键的值是系统呈现给用户的字符串 您的应用第一次尝试使用 Face ID 时。该字符串应该 清楚地解释为什么您的应用程序需要访问此身份验证 机制。系统不需要可比的使用描述 用于触摸 ID。

  • 确保您已添加安全性和本地身份验证 除了开启钥匙串(keychain)服务之外的框架

  • 您必须专门设置身份验证参数 SecAccessControlCreateWithFlags 类(请清楚地看一遍,它有很多区别)

请在此处查找更多信息以及示例源代码

https://developer.apple.com/documentation/localauthentication/accessing_keychain_items_with_face_id_or_touch_id

希望这有帮助。

关于ios - 使用私钥和 TouchID 或 FaceID swift 对消息进行签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56629494/

相关文章:

Ios Swift 日期从时区转换

ios持久化存储框架

java - 在 Java 中实现 SHA1withRSA

java - 在 Java 中使用 RSA 私钥加密

c++ - 第二次调用 RSA_private_decrypt 时崩溃

ios - UITextField 占位符具有不同的字体大小

ios - 在 tableviewCell 中快速实现一个类似的按钮

ios - Swift 如何制作像这张图片一样的背景?

ios - 如何在 UITableView 中引用 UITableViewCell

ios - focusStyle 在 UITableViewCell 中的作用是什么?