skip to Main Content

I am trying to import a certificate to the device keychain, which I am getting my API. I have used these references to save received data in certificate format. references: (SecPKCS12Import returns different results on iOS 11 than on iOS 10)
and Add Certificate to IOS Keychain in Swift
By doing some modifications to add the certificate to the keychain I have done below code:

 ` func certificateFromCertificate(certP12: Data, psswd: String) {
        let decodedData =  certP12
        
        let keytmp : NSString = kSecImportExportPassphrase as NSString
        let options : NSDictionary = [keytmp : psswd]
        
        var certificateRef: SecCertificate? = nil
        
        var items : CFArray?
        
        let securityError: OSStatus = SecPKCS12Import(decodedData as CFData, options, &items)
        
        let theArray: CFArray = items!
        if securityError == noErr && CFArrayGetCount(theArray) > 0 {
            let newArray = theArray as [AnyObject] as NSArray
            let dictionary = newArray.object(at: 0)
            let secIdentity = (dictionary as AnyObject)[kSecImportItemIdentity as String] as! SecIdentity
            let securityError = SecIdentityCopyCertificate(secIdentity , &certificateRef)
            if securityError != noErr {
                certificateRef = nil
            }
        }
        
                var keychainQueryDictionary = [String : Any]()

                if let tempSecCert = certificateRef {
                    keychainQueryDictionary = [kSecClass as String : kSecClassCertificate, kSecValueRef as String : tempSecCert, kSecAttrLabel as String: "My Certificate"]
                }

                let summary =  SecCertificateCopySubjectSummary(certificateRef!)!  as String
                print("Cert summary: (summary)")

                let status = SecItemAdd(keychainQueryDictionary as CFDictionary, nil)

            print(SecCopyErrorMessageString(status, nil))

    }`

I am getting proper certificate summary and also this print(SecCopyErrorMessageString(status, nil))
is returning no error. Optional(No error.)

The doubt I have is whether this certificate is properly installed in the device keychain or not. How do I verify that? Please note I don’t want to trust the certificate forcefully.

I tried

var keychainQueryDictionary = [String : Any]()
    
if let tempSecCert = certificateRef {
  keychainQueryDictionary = [kSecClass as String : kSecClassCertificate, kSecValueRef as String : tempSecCert, kSecAttrLabel as String: "My Certificate"]
}
    
let summary =  SecCertificateCopySubjectSummary(certificateRef!)!  as String
print("Cert summary: (summary)")
    
let status = SecItemAdd(keychainQueryDictionary as CFDictionary, nil)

This will import the certificate to the keychain of the device. I want to verify if it is installed successfully.

2

Answers


  1. Your import code is correct.

    iOS does not offer a way to view these imported certificates on UI, you have to query them via Security API, this code loops through all certificates and filter the certificate by its X509 Common Name:

    func queryCertificate(with commonName: String) -> Bool{
      let query: [String: Any] = [
        kSecClass as String: kSecClassCertificate,
        kSecReturnRef as String: true,
        kSecMatchLimit as String: kSecMatchLimitAll
      ]
      
      
      var items: CFTypeRef?
      let status = SecItemCopyMatching(query as CFDictionary, &items)
      
      if status == errSecSuccess {
        if let certificates = items as? [SecCertificate] {
          for certificate in certificates {
            var commonName: CFString?
            if SecCertificateCopyCommonName(certificate, &commonName) == errSecSuccess, let cn = commonName {
              if cn == commonName {
                debugPrint("Found Cert:(certificate)")
                return true
              }
            }
          }
        }
      }
      
      print("Certificate not found")
      return false
    }
    

    You can get the common name with openssl or view it in KeyChain App after imported to macOS.

    enter image description here

    Login or Signup to reply.
  2. Of course, you can extract the .pem file through openssh to view the validity period of p12.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search