Search code examples
iosswiftsslx509multipeer-connectivity

How to create a SecIdentityRef to be used with MultiPeerConnectivity?


I need to implement an authentication part for MultiPeer Connectivity exchanges in a Swift iOS application. And so I need to create a SecIdentityRef object at the MCSession creation (like so MCSession(peer: myPeerId, securityIdentity: secIdentity, encryptionPreference: MCEncryptionPreference.Required)).

I already created a X509 certificate with Keychain access and saved it to a .p12 file. I also have a certificate in .cgi and .der formats that could be used.

I'd like to know if either of these certificates are worth to be used in my application, and how to use it if yes ? Is it possible to put the certificate directly in the project directory and import its data in the app or do I need to use a server to provide the certificate ?

Last but not least, I have no idea on how to create the SecIdentityRef from a given certificate. I've tried to browse Apple Developer's references for classes MCSession, SecIdentityRef, SecCertificateRef and even CFData but I found nothing that could possibly help me.


Solution

  • I figured out how to import a certificate for Multipeer Connectivity session establishment.

    In the example below we assume that we have the certificate under supportedFiles/certificate.p12. Moreover, your certificate has to be protected by a password as I've read that the certificate management API doesn't support unprotected certificates.

    func getIdentity (password : String?) -> SecIdentityRef? {
        // Load certificate file
        let path = NSBundle.mainBundle().pathForResource("certificate", ofType : "p12")
        let p12KeyFileContent = NSData(contentsOfFile: path!)
    
        if (p12KeyFileContent == nil) {
            NSLog("Cannot read PKCS12 file from \(path)")
            return nil
        }
    
        // Setting options for the identity "query"
        let options = [String(kSecImportExportPassphrase):password ?? ""]
        var citems: CFArray? = nil
        let resultPKCS12Import = withUnsafeMutablePointer(&citems) { citemsPtr in
            SecPKCS12Import(p12KeyFileContent!, options, citemsPtr)
        }
        if (resultPKCS12Import != errSecSuccess) {
            return nil
        }
    
        // Recover the identity
        let items = citems! as NSArray
        let myIdentityAndTrust = items.objectAtIndex(0) as! NSDictionary
        let identityKey = String(kSecImportItemIdentity)
        let identity = myIdentityAndTrust[identityKey] as! SecIdentity
    
        print("identity : ", identity)
    
        return identity as SecIdentityRef
    }
    

    However I still don't know whether having the certificate in the application files is a security threat.

    edit : Thanks neilco, his snippet helped me build my solution.