My company's product is Android and iOS mobile app which connects to our own backend. All interactions of the mobile app are with backend developed by our own company.

In such a situation, can the backend use a self signed certificate (instead of getting a certificate from CA) and pin this self-signed certificate on mobile app to make it more secure.

Please let me know if this strategy makes sense (or we still have to get SSL cert from a CA)

  • 2
    $\begingroup$ You can do both. Have a CA such as Let's Encrypt certify your certificate for your domain and pin the key in the application. LE enforces a tight expiration window (IIRC 60 days), support revocation, and if you've pinned the public key (not the "certificate" itself) then you can update the certificate without invaliding the pinning (so long that you don't change the keypair). You can think of this as if your pinning code were to fail, you should still trust the CA. Or it is easier than managing your own CA, certificate rotation policy and revocation lists. $\endgroup$ – cypherfox May 10 '18 at 3:23
  • $\begingroup$ @cypherfox , is there a tutorial on this available online. What you explained is scenario where certificate is issued for backend and key is pinned in application (mobile app or client side). Now for scenario where client/application/mobile app communicates with server, does it not need a certificate too? How is that scenario implemented.? $\endgroup$ – msgboardpana May 10 '18 at 19:45
  • $\begingroup$ @msgboardpana This is an implementation detail with the TLS provider you choose. I could search for one, just as you could. But it'll probably be better if you search with respect to the TLS provider that you'll be using. $\endgroup$ – cypherfox May 11 '18 at 1:37

Yes, this (certificate pinning) is the preferred method, since it removes the reliance on external authorities and makes man in the middle attacks even harder.

An additional step would be to obscure the pinned certificate inside the application to stop it easily being edited.


You can do both. First use a CA such as Let's Encrypt in a "normal" TLS setup. Then configure your clients to pin the public key part of the certificate such that the certificate may be regenerated as per LE's policy (expires after 90 days) without changing the public key itself.

There are various methods to pinning that work universally (when your TLS provider permits your control) and some are protocol-specific such as HPKP.

Firefox and Chrome disable pin validation for pinned hosts whose validated certificate chain terminates at a user-defined trust anchor (rather than a built-in trust anchor). This means that for users who imported custom root certificates all pinning violations are ignored.

As mentioned in the MDN article for HPKP (linked above), HTTP level pinning is ignored if you're using self signed certificates. Worse, if you're using some library such as libcurl that doesn't persist any state, the pinning request will be forgotten.

Ideally your TLS provider will allow you to enforce your custom public key pinning before sensitive information may be sent to an attacker. You should verify your client-side pinning is working as expected by using a test server with a valid certificate signed by LE but has a different public key as to break the pin.

Why do we still need a CA at all? A CA remains useful because they can revoke your certificate on your request if your server is compromised; which is faster than a mobile package manager will accept your updated client. Additionally, if your client's pinning code ever breaks (maybe your upstream library changed), you'll still have at least the security of the traditional unpinned TLS workflow.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.