{"id":54565,"date":"2026-06-03T17:54:02","date_gmt":"2026-06-03T15:54:02","guid":{"rendered":"https:\/\/cyberant.com\/pin-or-no-pin-the-trade-off-around-certificate-pinning-in-mobile-apps\/"},"modified":"2026-06-03T17:54:02","modified_gmt":"2026-06-03T15:54:02","slug":"pin-or-no-pin-the-trade-off-around-certificate-pinning-in-mobile-apps","status":"publish","type":"post","link":"https:\/\/cyberant.com\/en\/pin-or-no-pin-the-trade-off-around-certificate-pinning-in-mobile-apps\/","title":{"rendered":"Pin or no pin: the trade-off around certificate pinning in mobile apps"},"content":{"rendered":"<p>Certificate pinning sounds like the holy grail for a secure mobile app. Your app then no longer trusts every Certificate Authority that Android or iOS trusts by default, but only a pre-approved set of public keys. An attacker with a fraudulently issued or locally installed root certificate then has no chance. Still, the Android Developers documentation <a href=\"https:\/\/developer.android.com\/privacy-and-security\/security-ssl\" target=\"_blank\" rel=\"noopener\">explicitly advises against it<\/a>, mainly because of the operational risks when a server configuration changes. A future CA change or certificate rotation could render the app completely inaccessible, and a fix requires an app-store update that users only install when they want to.    <\/p>\n<h2 class=\"mt-6 mb-2 font-semibold text-2xl\" data-streamdown=\"heading-2\">Why pinning remains enticing<\/h2>\n<p>Standard TLS validation leans on the operating system&#8217;s trust store. In it are more than a hundred root CAs. If one of those CAs is compromised, or if malware or a corporate proxy places an additional root CA on the device, an attacker can present a valid-looking certificate for your API. For a banking app, a healthcare app or an application that controls industrial controls, this is unacceptable. OWASP therefore <a href=\"https:\/\/mas.owasp.org\/MASTG\/knowledge\/android\/MASVS-NETWORK\/MASTG-KNOW-0015\/\" target=\"_blank\" rel=\"noopener\">classifies<\/a> identity pinning as MASVS-NETWORK level 2 control, recommended for apps that process sensitive data.    <\/p>\n<h2 class=\"mt-6 mb-2 font-semibold text-2xl\" data-streamdown=\"heading-2\">The two golden rules<\/h2>\n<p>Those who do pin must follow two rules. The first is:<span class=\"font-semibold\" data-streamdown=\"strong\">pin public keys, not certificates.<\/span> A certificate changes every 60 to 90 days with automated vendors such as Let&#8217;s Encrypt, but the underlying key pair can remain static. The hash of the SubjectPublicKeyInfo, SPKI for short, is your pin. Generate it with OpenSSL:   <\/p>\n<div class=\"relative bg-neutral-100 dark:bg-neutral-800 rounded-2xl overflow-hidden my-6\">\n<pre class=\"hidden dark:block m-0 bg-neutral-800 text-sm overflow-x-auto p-4\"><code class=\"font-mono text-sm\">openssl s_client -connect api.jouwdomein.nl:443 | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl base64\n<\/code><\/pre>\n<\/div>\n<p><span class=\"font-semibold\" data-streamdown=\"strong\">The second is: always add a backup pin.<\/span>  That&#8217;s a second key pair that you keep offline and don&#8217;t hang in production yet. When you need to rotate, you put the backup pair on the server and the app already trusts it, no update needed. Only in a subsequent release do you introduce a new backup and delete the old primary.  <\/p>\n<p>Also remember that pinning is a line of defense, not an impenetrable wall. An attacker with root on the device can repackage the APK, modify the pins and re-sign the app. Therefore, pinning belongs in a broader strategy that includes Play Integrity, root detection, obfuscation and runtime checks.  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Certificate pinning sounds like the holy grail for a secure mobile app. Your app then no longer trusts every Certificate Authority that Android or iOS trusts by default, but only a pre-approved set of public keys. An attacker with a fraudulently issued or locally installed root certificate then has no chance. Still, the Android Developers [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":54562,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[206,216],"tags":[338,336],"class_list":["post-54565","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cyber-security","category-knowledge-base","tag-development","tag-secure-coding"],"_links":{"self":[{"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/posts\/54565","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/comments?post=54565"}],"version-history":[{"count":0,"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/posts\/54565\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/media\/54562"}],"wp:attachment":[{"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/media?parent=54565"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/categories?post=54565"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cyberant.com\/en\/wp-json\/wp\/v2\/tags?post=54565"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}