ecdsa.com

Key fingerprint · OpenSSL

How to compute a public key fingerprint with OpenSSL

With OpenSSL, the public key fingerprint is a two-command pipe: re-encode the key as binary SPKI DER, hash it with SHA-256. The same pipe pattern works whether you start from a public key, a private key or a certificate.

Tested with OpenSSL 3.6.

Same recipe in:Node.jsPythonGoOpenSSLWebCrypto
fingerprint of a public key
openssl pkey -pubin -in pub.pem -outform DER | openssl dgst -sha256 -c
# SHA2-256(stdin)= 21:2c:...:9d
from a private key or a certificate
# private key: derive the public half in the same pipe
openssl pkey -in key.pem -pubout -outform DER | openssl dgst -sha256 -c
 
# certificate: extract the key first (NOT the same as -fingerprint!)
openssl x509 -in cert.pem -pubkey -noout \
| openssl pkey -pubin -outform DER | openssl dgst -sha256 -c
base64 pin format (RFC 7469 pin-sha256)
openssl pkey -pubin -in pub.pem -outform DER \
| openssl dgst -sha256 -binary | openssl base64

How it works

  1. -outform DER is the crucial flag: it re-encodes the key as canonical binary SPKI, so every tool hashing the same key gets the same digest.
  2. dgst -c prints colon-separated hex; -binary | base64 produces the pin-sha256 form used in HTTP public key pinning.
  3. The certificate variant pipes through pkey deliberately — it normalizes the extracted PEM back to DER before hashing.

Gotchas

  • openssl dgst -sha256 pub.pem hashes the PEM *text* — line endings and wrapping included — and matches nothing computed from DER. The -outform DER pipe is not optional.
  • openssl x509 -fingerprint -sha256 is the *certificate* fingerprint (hash of the entire cert), which changes on every renewal; the key fingerprint from this recipe survives re-issue with the same key.
  • Newer OpenSSL prints the digest labeled SHA2-256(stdin)=; older builds say SHA256(stdin)=. Scripts that match the prefix textually break across versions — parse the hex after = instead.

Related recipes