Hey @eskimo thank you for your reply!
I followed your instructions, but identity does not appear in a keychain.
I manually compared public portion of a key generated in Secure Enclave with a public key of a certificate surfaced in Keychain Access.
They match, but I cannot see the certificate in a list of all available identities.
I also tried to manually create and add identity to the keychain. In this case SecItemAdd fails with -50 errSecParam.
Here is the code I'm using:
func run() {
let key = genKey()
let publicKey = SecKeyCopyPublicKey(key!)
let d = Data(referencing: SecKeyCopyExternalRepresentation(publicKey!, nil)!)
print("publicKey:", d.hexEncodedString()) // compare with a public key of a cert in Keychain Access app
let certificate = genCert(key: key!)
addCertificateToKeychain(certificate: certificate!)
// addIdentityToKeychain(certificate: certificate!)
listIdentities()
}
func genKey() -> SecKey? {
let access = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
.privateKeyUsage,
nil)!
let attributes: NSDictionary = [
kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits: 256,
kSecAttrTokenID: kSecAttrTokenIDSecureEnclave,
kSecPrivateKeyAttrs: [
kSecAttrIsPermanent: true,
kSecAttrAccessControl: access
]
]
return SecKeyCreateRandomKey(attributes, nil)
}
func genCert(key: SecKey) -> SecCertificate? {
// generate and return x509 certificate
}
func addCertificateToKeychain(certificate: SecCertificate) {
let addquery: [String: Any] = [kSecClass as String: kSecClassCertificate,
kSecValueRef as String: certificate]
let status = SecItemAdd(addquery as CFDictionary, nil)
print("SecItemAdd Certificate", status) // status 0
}
func addIdentityToKeychain(certificate: SecCertificate) {
var identity: SecIdentity?
let statusIDCreate = SecIdentityCreateWithCertificate(nil, certificate, &identity)
print("SecItemIdentityCreate", statusIDCreate) // status 0
let addquery: [String: Any] = [kSecClass as String: kSecClassIdentity,
kSecValueRef as String: identity!]
let status = SecItemAdd(addquery as CFDictionary, nil)
print("SecItemAdd Identity", status) // status -50 errSecParam
}
func listIdentities() {
let query: [String: Any] = [kSecClass as String: kSecClassIdentity,
kSecMatchLimit as String: kSecMatchLimitAll,
kSecReturnRef as String: true]
var item: CFTypeRef?
SecItemCopyMatching(query as CFDictionary, &item)
for id in item as! Array<SecIdentity> {
var certificate: SecCertificate?
SecIdentityCopyCertificate(id, &certificate)
let desc = SecCertificateCopyLongDescription(kCFAllocatorDefault, certificate!, nil)
print(desc!)
}
}
extension Data {
func hexEncodedString() -> String {
return self.map { String(format: "%02hhX ", $0) }.joined()
}
}
Am I doing something wrong?
Thank you
Topic:
Privacy & Security
SubTopic:
General
Tags: