我已使用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
}
}
}
}
和签名功能:
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)
}
答案 0 :(得分:0)
对不起,您的问题很长,所以我想我会给出一般性的答案。
确保已在自己的计算机中设置 NSFaceIDUsageDescription info.plist
没有此键,系统将不允许您的应用使用Face ID。的 此键的值是系统提供给用户的字符串 您的应用首次尝试使用Face ID。该字符串应 明确说明您的应用为何需要访问此身份验证 机制。该系统不需要类似的用法说明 触摸ID。
确保同时添加了安全性和LocalAuthentication 除了启用钥匙串服务之外的框架
您必须在以下位置专门设置身份验证参数 SecAccessControlCreateWithFlags类(请清楚地进行此操作,这会带来很大的不同)
请在此处找到更多信息以及示例源代码
希望这会有所帮助。
答案 1 :(得分:0)
请勿使用模拟器,请在真实设备上试用。
答案 2 :(得分:0)
您需要将标志设置为
let flags:SecAccessControlCreateFlags =
[SecAccessControlCreateFlags.privateKeyUsage, SecAccessControlCreateFlags.touchIDCurrentSet]