I am writing a MacOS app that uses the Apple crypto libraries to create, save, and use an RSA key pair. I am not using a Secure Enclave so that the private key can later the retrieved through the keychain. The problem I am running into is that on my and multiple other systems the creation and retrieval works fine. On a different system -- running MacOS 15.3 just like the working systems -- the SecKeyCreateRandomKey function appears to work fine and I get a key reference back, but on subsequent runs SecItemCopyMatching results in errSecItemNotFound. Why would it appear to save properly on some systems and not others?
var error: Unmanaged<CFError>?
let access = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.biometryAny,
&error)!
let tag = TAG.data(using: .utf8)! // com.example.myapp.rsakey
let attributes: [String: Any] = [
kSecAttrKeyType as String: KEY_TYPE, // set to kSecAttrKeyTypeRSA
kSecAttrKeySizeInBits as String: 3072,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: tag,
kSecAttrAccessControl as String: access,
],
]
guard let newKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
throw error!.takeRetainedValue() as Error
}
return newKey
This runs fine on both systems, getting a valid key reference that I can use. But then if I immediately try to pull the key, it works on my system but not the other.
let query = [ kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: tag,
kSecReturnRef as String: true, ]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
let msg = SecCopyErrorMessageString(status, nil)
if status == errSecItemNotFound {
print("key not found")
}
guard status == errSecSuccess else { print("other retrieval error") }
return item as! SecKey
I've also tried a separate query using the secCall function from here (https://developer.apple.com/forums/thread/710961) that gets ALL kSecClassKey items before and after the "create the key" function and it'll report the same amount of keys before and after on the bugged system. On the other machines where it works, it'll show one more key as expected.
In the Signing & Capabilities section of the project config, I have Keychain Sharing set up with a group like com.example.myapp where my key uses a tag like com.example.myapp.rsakey. The entitlements file has an associated entry for Keychain Access Groups with value $(AppIdentifierPrefix)com.example.myapp.