Post

Replies

Boosts

Views

Activity

Apple demo code for using kSecAttrLabel to retrieve a certificate doesn't work
I am following the code in the linked documentation below to add and retrieve a SecCertificate from the login keychain using the kSecAttrLabel attribute. The demo code in the linked page below isn't complete but the relevant parts in my code are lifted almost verbatim. Am I doing something wrong or is this a bug or is something deprecated? https://developer.apple.com/documentation/security/certificate_key_and_trust_services/certificates/storing_a_certificate_in_the_keychain The add portion of the code works fine but the retrieval fails with the error: The specified item could not be found in the keychain.. Visual inspection of the keychain shows the certificate in the login keychain under the 'Certificates' tab as expected. An alternative query to get the certificate back using the kSecMatchSubjectContains attribute works fine. I'm very new to Swift so pardon any terrible formatting or naming faux pas. In case its relevant I'm using: macOS 11.5.2 Xcode 12.5.1 Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55) Target: arm64-apple-darwin20.6.0 Demo code and data is below: import Foundation // a label to use in the storage and retrieval queries for SecItemAdd and SecItemCopyMatching let certLabel = "specialtestlabel" // a pem formatted certificate that we can use to add and try to retrieve from the default (login) keychain // note that I have deleted the private key and certificate so no security issues for me posting it here let certPEM = """ -----BEGIN CERTIFICATE----- MIIE9zCCA1+gAwIBAgIQc1P13Pj0F7xIYs9PVe5KgDANBgkqhkiG9w0BAQsFADCB kzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTQwMgYDVQQLDCtqc0BK b3Nocy1NYWNCb29rLUFpci5sb2NhbCAoSm9zaCBTY2hsZXNzZXIpMTswOQYDVQQD DDJta2NlcnQganNASm9zaHMtTWFjQm9vay1BaXIubG9jYWwgKEpvc2ggU2NobGVz c2VyKTAeFw0yMTA4MjQyMDEzMDhaFw0zMTA4MjQyMDEzMDhaMIGTMR4wHAYDVQQK ExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExNDAyBgNVBAsMK2pzQEpvc2hzLU1hY0Jv b2stQWlyLmxvY2FsIChKb3NoIFNjaGxlc3NlcikxOzA5BgNVBAMMMm1rY2VydCBq c0BKb3Nocy1NYWNCb29rLUFpci5sb2NhbCAoSm9zaCBTY2hsZXNzZXIpMIIBojAN BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwyDRTPGMvJwre8j73QnTLsjYBmmF 3HQmtp/pFDUqwuj16rMgh7jSjpXXLjqJfeCmPuuPFUTltkuINsnbycHuebJiirr5 gSw5tm/Yf25mZj4x+E3bGqo7t8z4IhSz9Qkx3Da03Mb9FnCs0eQx4B3SgH2ZA3Fa OznnD+5XBEnfHa6AzA1xxaFEtbS5FStYEysbpssEWmiflpBYIFfMqqLkup7SkFdm vDhpCrOlg9vxC4FaWExgVwgRFZvyrvZuwX0jwp09QZY7T8SLAoMRbv2ucSaD9PaC uwobdNn2p14qHQqTlPE5kj/SIWziUEgkAwDp4kVoz/jtlW/lTowobvtcDEAt5l7W zicVKxYGPJz1pkmFD9EBsKuOLPqdmsOP860d0naqM6qv08LJTSVpYc8l7w/8gwdi WT2Z+thdPke364gDzpOjl6CooKrE4lAgclShwHHr2XFgEZ7fSLcQivJAVPFr8o3f ZKcfEZgT4Njg5TjayacVTCatDQjWTphhe9u3AgMBAAGjRTBDMA4GA1UdDwEB/wQE AwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTgt9SlhsH0usZCeGF2 stxXP3TNiDANBgkqhkiG9w0BAQsFAAOCAYEAXvltDX5c9yiCLCw6RmAGRnk49YgF **8W7wLQn8NdudEGEtOtaPjFRjCa+QxIGMnYcYDhOQIqa6VrxyHLF4HvfuBveLP6 kQ0mYh8h41l7KSHSRqzHODPzoIEQQ4CQf9z0akpB2934ZfS7JT59eYBn+elAqKRh WHAW9cG+i+04FfQUrTDRjyIwTtfKNFR4eqombYzP9ozvZwmyTb2jDxk4l/KimBkB MmXYLehnPf8ombBAMoYOAS8XdUY21Wz3+F4uE4WyUse8pawdDWf8eVsRW3DW0wvd B75hZz7EVbXSj1xmrNRB3QWY6gleZH7lucrt/cqEHlV9MfWLkq85HAzRv3ZUSd32 GDuDcv6pwVPRUceO/flBr5nFqlr5ZOW6LxXVG7GV+hKGfJPv31jm4yntbkbDA5sp YcbEMUQP+4ZB9srHHYDG18ZOgnFW7YZuCLb32VS8L5hogAqYJJpwuL8gT2z2y3GP 6GBE9JdgjQwq1REgNTSr8Ry8ZimwlHfi7nk1 -----END CERTIFICATE----- """ enum CertError: Error { case PEMtoSecCertificateError case addTokeychainError case getFromkeychainError } // create a SecCertificate from the PEM string let PEMNoHeader = certPEM.split(separator: "\n").dropFirst().dropLast().joined(separator: "") let CertDER = Data(base64Encoded: PEMNoHeader)! guard let certificate = SecCertificateCreateWithData(nil, CertDER as CFData) else { print("There was an error creating the certificate") throw CertError.PEMtoSecCertificateError } let addquery: [String: Any] = [kSecClass as String: kSecClassCertificate, kSecValueRef as String: certificate, kSecAttrLabel as String: certLabel] let addStatus = SecItemAdd(addquery as CFDictionary, nil) guard addStatus == errSecSuccess else { print(SecCopyErrorMessageString(addStatus, nil)!) throw CertError.addTokeychainError } // for some reason this query doesnt work... :( let getQuery: [String: Any] = [kSecClass as String: kSecClassCertificate, kSecAttrLabel as String: certLabel, kSecReturnRef as String: kCFBooleanTrue!] // note that we arent using this here but if you use the below otherGetQuery, everything works as expected // i used mkcert to generate the certificate, it has been deleted off of my system let otherGetQuery: [String: Any] = [kSecClass as String: kSecClassCertificate, kSecMatchSubjectContains as String: "mkcert", kSecReturnRef as String: kCFBooleanTrue!] // lets try to get the certificate back from the keychain var item: CFTypeRef? let copyStatus = SecItemCopyMatching(getQuery as CFDictionary, &item) guard copyStatus == errSecSuccess else { print(SecCopyErrorMessageString(copyStatus, nil)!) throw CertError.getFromkeychainError } // if we make it to here, everything below this comment works as expected let certificateKeychain = item as! SecCertificate let CertDERKeychain = SecCertificateCopyData(certificateKeychain) as Data print(CertDER.base64EncodedString()) print(CertDERKeychain.base64EncodedString())
5
0
1.6k
Aug ’21