Search code examples
iossecuritysslpinning

iOS - how do I get server certificate into iOS client keychain for pinning


TL;DR version: Is there any way to pass a Server certificate to an iOS client that doesn't involve also passing along the Server's private key?

I have written an iOS client app that communicates with my macOS server app (so I have control over both ends). I have implemented certificate pinning using a self-signed certificate to make things more secure. To accomplish this during development, I hardcoded the Server cert into the iOS client app and told the client to only connect to a server that gives you that exact cert during the TLS handshake. Everything is working great.

However in the real world I am selling this system as a set (1 Server, multiple clients to each customer), so I cannot hardcode a Server cert into the iOS client. My plan is to instead deliver the Server cert out of band (via email) to the iOS client like mentioned here: Making Certificates and Keys Available To Your App:

Apps can only access keychain items in their own keychain access groups.

To use digital identities in your own apps, you will need to write code to import them. This typically means reading in a PKCS#12-formatted blob and then importing the contents of the blob into the app's keychain using the function SecPKCS12Import

One way to provision an identity is via email. When you provision a device, send the associated user an email with their client identity attached as a PKCS#12 file.

My problem is that a .p12 file contains the certificate and the private key of the server - this seems very wrong to pass the private key along as well.

Is there any other way to pass the Server certificate to the iOS client that doesn't involve also passing along the Server's private key?

Thanks!!!


Solution

  • I was overthinking things here, the solution is actually pretty simple.

    I just needed to email the Server's public certificate out of band to the client device with a custom extension like cert.myCustomExt1234. This is because the .crt extension is already claimed by iOS so you have to register your app to handle custom extensions (see apple docs here). Then in my app I can do all the logic of cert pinning using that out of band delivered Server public cert.

    The key was changing the file extension to something not already claimed by iOS.