Certificate pinning mobile apps

976 views Asked by At

I am trying to implement certificate pinning on my app. As far as I understood there are 3 types of pinning available:

  • certificate pinning; The certificate should be "hardcoded" in the app and compared with the ones from the server. This is kind of bad because if a certificate needs to be rotated an update of the app is required.
  • public key pinning; From my research it seems this is deprecated
  • SubjectPublicKeyInfo(SPKI) pinning; this is a hash of the public key. The advantage with this approach is that if a certificates neeeds to be rotated the public key of the new certificate can remain the same for the new certificate, this way an update is not required.

Based on what I've said, it seems that the recommended way to do this is SPKI pinning.

My app can connect to multiple servers, based on the ip which the user types at login. This is my idea of implementing but I am not sure it would work.

I would create an Intermediate Certificate signed by a CA. Then create my own public-private keys. Then each server that my app can connect would need to request from me to sign their certificate with my private key. The hierarchy would be something of RootCertificate(self signed by CA), then my intermediate certificate(signed by CA) and then leafs certificates for every server that my app could connect signed by my private key.

On the app I would store the hash of the public key from my intermediate certificate. Upon first connection to a random server the app will get 3 certificates: the one for the server, my intermediate certificate and the Root Certificate. When checking the hashes will find a match with my public key.

What do you think? Could this be implemented? Did I understand something wrong? Is this approach prone to mitm attack? Thanks!

1

There are 1 answers

0
Exadra37 On

My app can connect to multiple servers, based on the ip which the user types at login. This is my idea of implementing but I am not sure it would work.

I would create an Intermediate Certificate signed by a CA. Then create my own public-private keys. Then each server that my app can connect would need to request from me to sign their certificate with my private key. The hierarchy would be something of RootCertificate(self signed by CA), then my intermediate certificate(signed by CA) and then leafs certificates for every server that my app could connect signed by my private key.

On the app I would store the hash of the public key from my intermediate certificate. Upon first connection to a random server the app will get 3 certificates: the one for the server, my intermediate certificate and the Root Certificate. When checking the hashes will find a match with my public key.

I would simplify this approach and just pin against each backend server and the Mobile Certificate Pinning Generator tool can help you with extracting the pins for multiple domains/ips, while generating the proper pinning configurations to use in Android and iOS.

Let's imagine that your mobile app needs to communicate with example.com, httpbin.org and google.com.

Just configure the domains you want to pin against in the Config tab:

Config tab

After you submit the form you will land in the Results tab, and then if you navigate to the Android tab:

Android network security config file

and on the iOS tab:

iOS info.plist pinning configuration

Below each configuration you have instructions on how to add each configuration into your mobile project and even a link to a step by step tutorial on Github that uses the Pin Test App for Android and iOS.

The advantage of pinning against each backend certificate is that you can now have each one auto generating their certificates with LetsEncrypt that keeps the public key between renewals, thus without the need to change the pins in the mobile app, unless a compromise of the private keys occurs. You can replace LetsEncrypt it whatever allows you to rotate certificates while maintaining the same public key.