簡體   English   中英

使用私鑰和 TouchID 或 FaceID swift 簽署消息

[英]Signture the message with private key and TouchID or FaceID swift

我用SecKeyCreateRandomKey在鑰匙串中創建了一個私鑰。 當我嘗試訪問密鑰以執行簽名操作時,永遠不會出現 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)
}

對不起,你的問題很長,所以我想我會給出通用的答案。

  • 確保您在 info.plist 中設置了NSFaceIDUsageDescription

    如果沒有此密鑰,系統將不允許您的應用使用面容 ID。 此鍵的值是系統在您的應用首次嘗試使用面容 ID 時向用戶呈現的字符串。 該字符串應清楚地解釋為什么您的應用程序需要訪問此身份驗證機制。 系統不需要 Touch ID 的類似使用說明。

  • 確保除了打開鑰匙串服務之外,您還添加了 Security 和 LocalAuthentication 框架

  • 您必須在 SecAccessControlCreateWithFlags 類中專門設置 Authentication 參數(請清楚地通過它,這有很大的不同)

請在此處找到更多信息以及示例源代碼

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

希望這可以幫助。

不要使用模擬器,在真實設備上嘗試。

您需要將標志設置為

let flags:SecAccessControlCreateFlags = 
 [SecAccessControlCreateFlags.privateKeyUsage, SecAccessControlCreateFlags.touchIDCurrentSet]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM