I have a KeyChain class where I sign a string.
I got Thread 8: EXC_BAD_ACCESS (code=257, address=0x3fd574bc6a7ef9db)
error at SecKeyIsAlgorithmSupported
function. I could not figure out why this error pops up.
When I use the getquery
variable which is commented it all works fine except on iPhone 13 pro max devices. So I wanted to try different queries hoping that can work on all devices. But in that case SecKeyIsAlgorithmSupported function crashes giving this error EXC_BAD_ACCESS
. Here is the function I use.
func signString(clearString:String) -> Bool {
/*let getquery: [String: Any] = [kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: serviceName,
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecReturnRef as String: true]*/
let getquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceName,
kSecReturnAttributes as String: kCFBooleanTrue!,
kSecMatchLimit as String: kSecMatchLimitAll]
var item: CFTypeRef?
let status = SecItemCopyMatching(getquery as CFDictionary, &item)
print("status = ",status)
if (status != errSecSuccess) {
print("No key found")
return false
}
else {
let key = item as! SecKey
self.privateKey = key
let data = clearString.data(using: .utf8)! as CFData
let algorithm: SecKeyAlgorithm = .ecdsaSignatureMessageX962SHA256
if (self.privateKey != nil) {
guard SecKeyIsAlgorithmSupported(self.privateKey!, .sign, algorithm) else {
print("Algorithm Not Supported")
return false
}
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(self.privateKey!,algorithm, data, &error) as Data? else {
print("signature error")
return false
}
self.signedString = signature.base64EncodedString()
return true
}
else {
print("Private Key is null")
return false
}
}
}
I wish there would be a way to avoid this crash. I searched about it but I could not find a way to fix that. Any help will be appreciated. Thanks in advance.
Your get query states kSecMatchLimitAll
, which will result in a CFArray
object as a result. You can easily fix that by changing it to kSecMatchLimitOne
, or you can loop the list, by casting it to an array.
let keys = item as! [SecKey]
for key in keys {
SecKeyIsAlgorithmSupported(key, .sign, . ecdsaSignatureMessageX962SHA256)
}
Do note that not all generic items, or likely none, are valid SecKey
objects. It appears you're using ECC keys, which can be stored using the kSecClass: kSecClassKey
attribute. I would highly recommend storing it as what it is, instead of storing it as a generic password (kSecClassGenericPassword
) as you're doing right now