Записать сообщение закрытым ключом и TouchID или FaceID swift - PullRequest
0 голосов
/ 17 июня 2019

Я создал закрытый ключ в связке ключей с SecKeyCreateRandomKey.Когда я пытаюсь получить доступ к ключу для выполнения операции подписи, диалоговое окно Touch ID или FaceID никогда не появляется.Я получаю строку знака, но без TouchID или FaceID.Я пробовал с BiometryAny и TouchIdAny, но это не работает.

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
            }
          }
       }
    }

и функция signture:

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)
}

Ответы [ 2 ]

0 голосов
/ 18 июня 2019

Не используйте симулятор, попробуйте его на реальном устройстве.

0 голосов
/ 17 июня 2019

Извините, ваш вопрос довольно длинный, поэтому я подумал, что дам общий ответ.

  • Убедитесь, что вы установили NSFaceIDUsageDescription в своем info.plist

    Без этого ключа система не позволит вашему приложению использовать Face ID. значение для этого ключа - строка, которую система представляет пользователю в первый раз ваше приложение пытается использовать Face ID. Строка должна четко объясните, почему вашему приложению необходим доступ к этой аутентификации механизм. Система не требует сопоставимого описания использования для Touch ID.

  • Убедитесь, что вы добавили как Security, так и LocalAuthentication фреймворк, кроме включения служб цепочки для ключей

  • Вы должны специально установить параметр аутентификации в Класс SecAccessControlCreateWithFlags (пожалуйста, пройдите это ясно, это имеет большое значение)

Более подробную информацию и пример исходного кода вы найдете здесь

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

Надеюсь, это поможет.

...