Я создал закрытый ключ в связке ключей с 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)
}