Much like HTTP Strict Transport Security (HSTS), HTTP Public Key Pinning (HPKP) is a Trust-On-First-Use (TOFU) mechanism. It protects HTTPS websites from impersonation using certificates issued by compromised certificate authorities. The data for Pinning is supplied by an HTTP-Header sent by the WebServer.

25.2.1. HPKP Header Directives

HPKP provides two different types of headers:

Public-Key-Pins

Public-Key-Pins-Report-Only

HPKP header can be parametrized by following directives:

pin-sha256 is a required directive. It can and should be used several (at least two) times for specifying the public keys of your domain-certificates or CA-certificates. Operators can pin any one or more of the public keys in the certificate-chain, and indeed must pin to issuers not in the chain (as, for example, a backup-pin). Pinning to an intermediate issuer, or even to a trust anchor or root, still significantly reduces the number of issuers who can issue end-entity certificates for the Known Pinned Host, while still giving that host flexibility to change keys without a disruption of service. OpenSSL can be used to convert the public-key of an X509-certificate as follows:

$ openssl x509 -in <certificate.cer> -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 writing RSA key pG3WsstDsfMkRdF3hBClXRKYxxKUJIOu8DwabG8MFrU=

This piped usage of OpenSSL first gets the Public-Key of <certificate.cer>, converts it do DER (binary) format, calculates an SHA256 Hash and finally encodes it Base64. The output (including the ending Equal-Sign) is exactly whats needed for the pin-sha256="<YOUR_PUBLICKEY_HASH⇒" parameter.

To generate the hash for a prepared backup-key just create a certificate-signing-request and replace openssl x509 by openssl req -in <backup-cert.csr> -pubkey -noout as first OpenSSL command.

Instead of using OpenSSL even web-services like https://report-uri.io/home/pkp_hash/ can be used to get a suggestion for the possible Public-Key-Hashes for a given website.

max-age is a required directive (when using the Public-Key-Pins header). This directive specifies the number of seconds during which the user agent should regard the host (from whom the message was received) as a "Known Pinned Host".

includeSubdomains is an optional directive. This directive indicates that the same pinning applies to this host as well as any subdomains of the host’s domain name. Be careful - you need to use a multi-domain/wildcard-certificate or use the same pub/private-keypair in all subdomain-certificates or need to pin to CA-certificates signing all your subdomain-certificates.