SPKI Pin Generator

Both kinds of pin, and a straight answer about which to use. A key pin survives renewal if the key is reused; a certificate pin binds tighter and breaks every time.

What a pin is

A pin is a SHA-256 hash of something a server presents, stored inside an application and checked on every connection. If the value does not match, the connection is refused — whatever the system trust store says about it.

It exists to close a specific hole: the ordinary trust model accepts a certificate from any of the hundred-odd CAs your device trusts. Pinning narrows that to one key you chose.

Two things you can pin, and they are not equivalent

This tool produces both. Which one you choose decides whether pinning is something you maintain or something that maintains you.

Public key pin (SPKI)

Hashes only the SubjectPublicKeyInfo — the key and its algorithm — and ignores everything else in the certificate.

Certificate pin

Hashes the entire DER certificate. It is the same value your browser calls the SHA-256 fingerprint, shown as hex there and base64 here.

Which to use

Pin the key for anything shipped to people you cannot update on demand. That is almost every mobile app.

Pin the certificate only when both ends are yours and change together: a device talking to one fixed endpoint, or an internal service running a long-lived self-signed certificate you rotate deliberately. In those cases the tighter binding is worth the coupling, because the renewal is your own deployment anyway.

The pin is the base64, and nothing else

The value itself is just the digest: D18c7440RjXoF6av9C2BHoEQFXoFpM8cYjhsJGvx4sE=. Everything you see wrapped around it belongs to one particular library, and using the wrong wrapper is the most common way a perfectly correct pin gets rejected at runtime.

Where it goesWhat to write
Android network_security_configthe bare base64, inside <pin digest="SHA-256">
iOS / TrustKitthe bare base64
OkHttp CertificatePinnersha256/ then the base64 — one slash
curl --pinnedpubkeysha256// then the base64 — two slashes

The results panel prints each of these next to the pin, so there is nothing to remember.

Why there is no SHA-1 option

Reasonable question, because SHA-1 is everywhere around certificates. Your browser's certificate viewer prints a SHA-1 fingerprint. So does keytool -list. And Firebase and the Google Cloud console ask for "the SHA-1 fingerprint" when you register an Android app — which is the likeliest source of the confusion, and is a different thing entirely: that identifies your app signing certificate to Google's APIs, and has nothing to do with pinning a server's certificate on the network.

For pinning itself, SHA-256 is what the implementations take. HPKP only ever allowed pin-sha256. Android's network_security_config documents SHA-256 as the only supported digest. OkHttp will still accept a sha1/ prefix, but deprecates it.

And it should be deprecated: SHA-1 collisions have been practical since 2017, and chosen-prefix collisions since 2020 at a cost in the tens of thousands of dollars. For a pin that matters — an attacker who can produce two certificates sharing a hash gets you to pin one and presents the other. It is an expensive attack and not a likely one, but there is nothing to weigh against it, because SHA-256 is supported everywhere SHA-1 is.

The backup pin is not optional

Pinning converts a key loss into an outage you cannot fix from your side. If the pinned key is lost, compromised, or has to be rotated in a hurry, every copy of your app that shipped with that single pin stops connecting — and it keeps failing until each user installs an update. Some never will.

So pin at least two keys: the one in use, and a spare generated now, kept offline, and not deployed anywhere. When the first has to go, the second is already trusted by every client in the field. This tool will not let you paste the same key twice.

Where pins actually work

Not in browsers. The Public-Key-Pins header (HPKP) was removed from every major browser by 2018. Too many sites pinned a key they then lost and made their own domain unreachable for months, with no way to undo it. If you find a tutorial recommending the header, it is out of date.

Common problems

Related