I am new to iOS development, and recently I was trying to build an application, which will create a key inside the secure element, and after - I will sing something with it. While developing I've encountered an issue: the key generation fails if there is a flag .biometryAny or .biometryCurrentSet
The authentication itself is triggered, but the function still throws a mistake.
My setup - Xcode iPhone15 simulator, FaceID enrolled and the animation of it is working.
Ive created the same post on overflow, in case somebody will have the same issues:
https://stackoverflow.com/questions/78175858/secure-enclave-key-generation-failure
I've tried deleting the flag, while keeping the manual authorisation, and this approach works, but I still would like have maximum security.
THIS WORKS:
func authenticateUser(completion: @escaping (Bool, Error?) -> Void) {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Biometric authentication is needed to access your secure data."
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
DispatchQueue.main.async {
completion(success, authenticationError)
}
}
} else {
// Biometry is not available or not enrolled.
DispatchQueue.main.async {
completion(false, error)
}
}
}
@objc func encryptAction() {
authenticateUser { [weak self] (success, error) in
guard success else {
self?.outputLabel.text = "Authentication failed: \(error?.localizedDescription ?? "Unknown error")"
return
}
guard let randomNumber = self?.inputTextField.text, !randomNumber.isEmpty,
let dataToSign = randomNumber.data(using: .utf8),
let privateKey = self?.generatePrivateKey() else {
self?.outputLabel.text = "Error: Could not generate private key."
return
}
if let signature = self?.signData(privateKey: privateKey, data: dataToSign) {
self?.outputLabel.text = "Signature: \(signature.base64EncodedString())"
} else {
self?.outputLabel.text = "Error: Could not sign data."
}
}
}
func generatePrivateKey() -> SecKey? {
// 1. Create Keys Access Control
guard let accessControl =
SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage],
nil)
else {
fatalError("cannot set access control")
}
// 2. Create Key Attributes
guard let tag = "com.example.keys.mykey".data(using: .utf8) else {
fatalError("cannot set tag")
}
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: tag,
kSecAttrAccessControl as String: accessControl
]
]
// 3. Generate Key Pairs
var error: Unmanaged<CFError>?
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
if let error = error?.takeRetainedValue() {
print("Error creating a key: \(error)")
}
return nil
}
return privateKey
}
func signData(privateKey: SecKey, data: Data) -> Data? {
let digest = sha256(data: data)
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(privateKey,
.ecdsaSignatureMessageX962SHA256,
digest as CFData,
&error) as Data? else {
print(error!.takeRetainedValue() as Error)
return nil
}
return signature
}
}
THIS DOESN'T
guard let accessControl =
SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage, .biometryCurrentSet],
nil)
else {
info.something file is updated and there is a privacy FaceID field included.
the error is triggered at this part:
var error: Unmanaged<CFError>?
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
if let error = error?.takeRetainedValue() {
print("Error creating a key: \(error)")
}
return nil
}
The error itself:
Error creating a key: Error Domain=NSOSStatusErrorDomain Code=-25293 "Key generation failed, error -25293" UserInfo={numberOfErrorsDeep=0, NSDescription=Key generation failed, error -25293}
Post
Replies
Boosts
Views
Activity
Hello!
the other day I had troubles with running the application to interact with the Secure Enclave. (https://developer.apple.com/forums/thread/748611?page=1#783968022)
While my program is running perfectly fine now, I still have questions regarding its security.
QUESTIONS:
Is there any functionality just with the public key to get an evidence of a corresponding private key to be protected by the Secure Enclave without showing the source code?
Even with the most recent update of iOS 17.4, there is still no way to directly access the functionality of a Secure Element itself, is that right? So far I found a function SecureElementPass, and it seems like it’s the only interaction possible.
What is the difference between using Security API and Apple CryptoKit? I heard some were saying it the matter of habit and device support, but I still would like to hear an opinion of a professional.
Any information regarding that will be helpful. Thank you in advance for your time and effort!