我在钥匙串中创建了一个私钥,SecKeyCreateRandomKey
. 当我尝试访问密钥以执行签名操作时,"触控 ID "或"面容 ID"对话框将永远不会出现。我得到了符号字符串,但没有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
}
}
}
}
和签名功能:
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 ""
}
}
和获取私钥功能:
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)
}
抱歉,您的问题很长,所以我想我会给出通用答案。
确保已在信息列表
如果没有此密钥,系统将不允许你的应用使用面容 ID。这 此键的值是系统向用户显示的字符串 您的应用首次尝试使用面容 ID 的时间。字符串应 清楚地说明为什么你的应用需要访问此身份验证 机制。系统不需要类似的使用说明 对于触控 ID。
确保已添加安全性和本地身份验证 打开钥匙串服务以外的框架
您必须专门设置身份验证参数 SecAccessControlCreateWithFlags类(请清楚地通过这个,它有很大的不同)
请在此处找到更多信息以及示例源代码
https://developer.apple.com/documentation/localauthentication/accessing_keychain_items_with_face_id_or_touch_id
希望这有帮助。
不要使用模拟器,在真实设备上尝试。
您需要将标志设置为
let flags:SecAccessControlCreateFlags =
[SecAccessControlCreateFlags.privateKeyUsage, SecAccessControlCreateFlags.touchIDCurrentSet]