Public-Key-Pins

The HTTP Public-Key-Pins response header instructed browsers to associate specific cryptographic public key hashes with a domain, rejecting future TLS connections presenting certificates with different keys.

Legacy

HTTP Public Key Pinning (HPKP) was defined in its specification and has been deprecated. Chrome and Firefox removed HPKP support. No modern browser implements this header. Certificate Transparency (CT) replaced HPKP as a safer alternative for certificate verification. CT is now enforced by default in all major browsers without requiring any header.

Usage

Public-Key-Pins was part of the HTTP Public Key Pinning (HPKP) mechanism. A server included one or more Base64-encoded SHA-256 hashes of public keys from its certificate chain, along with a max-age value specifying how long the browser remembered the pins. On subsequent visits within the pin lifetime, the browser verified the presented certificate chain contained at least one pinned key. A mismatch caused the connection to fail entirely.

The intent was to protect against misissued certificates. If a certificate authority was compromised or tricked into issuing a fraudulent certificate for a domain, pinned browsers rejected the forged certificate because its public key hash did not match any stored pin.

HPKP carried serious operational risk. A misconfigured pin, a lost private key, or a routine certificate rotation without updating pins locked legitimate users out of the site for the duration of max-age. Some configurations set max-age to months, making recovery from a mistake extremely difficult. This risk of self-imposed denial of service was the primary reason browsers removed support.

Directives

pin-sha256

The pin-sha256 directive contains a Base64-encoded SHA-256 hash of a certificate's Subject Public Key Info (SPKI). At least two pin-sha256 directives are required: one matching a key in the current certificate chain and one backup pin for a key not yet deployed. The backup pin allows recovery if the primary key is lost or rotated.

max-age

The max-age directive specifies the number of seconds the browser remembers the pin set. After this period expires, the browser accepts any valid certificate for the domain again. Common values ranged from 5184000 (60 days) to 31536000 (one year).

includeSubDomains

The includeSubDomains directive extends the pin policy to all subdomains of the host. Without this directive, pins apply only to the exact hostname in the request.

report-uri

The report-uri directive specifies a URL where the browser sends JSON violation reports when a pin validation failure occurs. This allowed operators to detect certificate mismatches without blocking the connection, especially when used with the related Public-Key-Pins-Report-Only header during testing.

Example

A server pins three public key hashes with a 60-day lifetime. The first hash matches the current certificate's public key, and the remaining hashes serve as backups for planned key rotations. The includeSubDomains directive extends the policy across all subdomains.

Public-Key-Pins: pin-sha256="WrVO/NVwDzspUoFoRGbR0vR7gEj25C/saZilznWAQlM="; pin-sha256="5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w="; pin-sha256="r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E="; max-age=5184000; includeSubDomains

A minimal configuration pins a single key along with a backup and sets a 10-day lifetime. Shorter max-age values reduce the risk window from misconfigured pins.

Public-Key-Pins: pin-sha256="cN0QSpPIkuwpT6iP2YjEo1bEwGpH/yiUn6yhdy+HNto="; pin-sha256="WGJkyYjx1QMdMe0UqlyOKXtydPDVrk7sl2fV+nNm1r4="; max-age=864000

Takeaway

The Public-Key-Pins header was a TLS security mechanism allowing sites to pin certificate public keys, preventing connections with unauthorized certificates. The risk of misconfiguration locking out legitimate users led browsers to remove support, and Certificate Transparency now provides certificate monitoring without the self-denial risk.

See also

Last updated: March 6, 2026