Public Key Pinning Extension for HTTP
Extracted elements (30)
A max-age value around 60 days (5,184,000 seconds) is suggested as a balance between providing a narrow window of protection for infrequent visitors (low max-age) and risking UA inability to validate if pinned keys diverge (high max-age). No single ideal value exists for all use cases.
Pins are computed over the SubjectPublicKeyInfo (SPKI) structure rather than over entire certificates, so that operators can generate new certificates reusing existing public keys without breaking pinned clients. This enables certificate renewal without re-pinning.
Public Key Pinning is a trust-on-first-use (TOFU) mechanism: the UA cannot detect a MITM on the very first connection because it has no prior pinning state. A MITM on the first connection can also inject a hostile PKP header. The spec acknowledges nothing short of pre-shared keys can defend against a first-connection MITM.
Internationalized domain names used in UA processing MUST be canonicalized according to the scheme in Section 10 of RFC 6797 (HSTS). HPKP is designed to be used together with HSTS but can also be deployed independently.
When the host in a report-uri is itself a Known Pinned Host, UAs MUST perform Pin Validation for that report-uri connection; similarly, HSTS MUST be applied if the report-uri host is a Known HSTS Host. This prevents report delivery from bypassing security policies.
A UA MUST note Pins for a host only if all three conditions hold: the PKP header was received over an error-free TLS connection; the TLS connection was authenticated with a certificate chain containing at least one SPKI matching a given fingerprint; and the pin set contains at least one Backup Pin not referencing an SPKI in the current chain.
If a UA receives more than one PKP header field or more than one PKP-RO header field in an HTTP response, it MUST process only the first of each kind. PKP and PKP-RO headers received over insecure transport or that are not Valid Pinning Headers MUST be ignored.
If connecting to the report-uri itself incurs a Pin Validation failure or other certificate validation failure, the UA MUST cancel the connection. The UA SHOULD detect and break reporting loops between mutually-pinned hosts that both fail Pin Validation.
Known Pinned Hosts are identified only by domain names, never IP addresses. If the host in the Request-URI matches an IP-literal or IPv4address production, the UA MUST NOT note this host as a Known Pinned Host.
Pinned Hosts SHOULD NOT include the PKP header field in HTTP responses over non-secure transport, and UAs MUST ignore any PKP header received over non-secure transport.
The max-age directive is REQUIRED in a Public-Key-Pins header and specifies the number of seconds the UA SHOULD treat the host as a Known Pinned Host. The max-age directive is meaningless in a PKP-RO header and UAs MUST ignore it there and not cache the header.
The UA MUST NOT modify any pinning metadata of any superdomain-matched Known Pinned Host, and MUST NOT cache information derived from a PKP-RO header (PKP-RO headers are ephemeral).
UAs MAY set an upper limit on the max-age value to allow recovery from erroneous or maliciously set pins. If the server's max-age exceeds the UA's cap, the UA MAY behave as if the server set max-age to the UA's upper limit.
UAs MUST ignore any PKP header fields that do not conform to the specified grammar, and MUST NOT attempt to fix malformed header fields. If a directive is unrecognized, it MUST be ignored; recognized directives MUST be processed if the header otherwise conforms.
UAs MUST NOT heed http-equiv='Public-Key-Pins' or http-equiv='Public-Key-Pins-Report-Only' attributes on HTML <meta> elements; pinning can only be established via HTTP response headers over secure transport.
When a UA connects to a Known Pinned Host via TLS and the connection has errors, the UA MUST terminate the connection without allowing the user to proceed. If connection is error-free, the UA SHOULD perform Pin Validation by checking that the set of SPKI fingerprints in the certificate chain intersects the noted Pinning Metadata; if not, the UA MUST treat this as a non-recoverable error.
When formulating the JSON POST body for a failure report, the UA MUST either use single-quoted JSON strings or use double-quoted JSON strings and backslash-escape the embedded double quotes in the known-pin quoted-string part.
When max-age is 0, the UA MUST remove its cached Pinning Policy for a Known Pinned Host, or MUST NOT note the host if not yet known. This provides a way for operators to de-pin a host.
When the PKP-RO header is used, the UA MUST NOT enforce Pin Validation — it performs the check only to determine whether to POST a report. The UA MUST process the PKP header and SHOULD process both headers when both are present.
HPKP can be abused as a 'super-cookie' to track users: a host can encode distinct arbitrary identifiers in pin values and use report-uri callbacks or subdomain connection failures to fingerprint individual UAs across sessions, even after cookies are cleared. UAs should allow users to clear pinning state and query current pinned hosts.
Pin Validation failure reports contain certificate chain information; in cases of organization-wide TLS interception, these reports may disclose the interception infrastructure to the report-uri operator. Additionally, the pinning state store reveals which domains a UA has visited, even after other browser state is cleared.
An SPKI Fingerprint is the output of SHA-256 applied to the DER-encoded ASN.1 SubjectPublicKeyInfo structure of an X.509 certificate, base64-encoded for use in the HTTP header. A Pin is the combination of the algorithm identifier and the computed SPKI Fingerprint.
The OPTIONAL includeSubDomains directive, when asserted, extends the Pinning Policy to all subdomains of the host's domain name. The OPTIONAL report-uri directive specifies a URI to which the UA SHOULD POST Pin Validation failure reports as a JSON object.
The Public-Key-Pins (PKP) and Public-Key-Pins-Report-Only (PKP-RO) response header fields instruct user agents to perform Pin Validation for the host emitting the response. Both headers share the same ABNF grammar: a semicolon-separated list of directives, each a token optionally followed by '=' and a token or quoted-string value.
This document registers two permanent HTTP response header field names — 'Public-Key-Pins' and 'Public-Key-Pins-Report-Only' — in the IANA 'Message Headers' registry with protocol 'http' and status 'standard'.
Hostile pinning: an attacker who obtains a valid certificate for a domain (through CA misissuance or prior domain ownership) can serve a Valid Pinning Header that pins the UA to the attacker's keys, blocking access to the legitimate site for the duration of max-age. Mitigation includes capping max-age and preloading legitimate pins.
Operators MUST include at least one Backup Pin — a fingerprint for a secondary not-yet-deployed key pair kept offline. Without a backup pin, loss of the primary private key would make the host inaccessible to UAs for the entire pin lifetime. UAs enforce this requirement by rejecting PKP headers without a backup pin.
Using the includeSubDomains directive can cause Pin Validation failures for subdomains that legitimately use different certificate chains, depending on the order in which a UA encounters Valid Pinning Headers. Operators must use overlapping pin sets or coordinate pin sets across parent and subdomain hosts.
Pin Validation failure reports are JSON objects POSTed to the report-uri, containing: date-time (RFC 3339), hostname, port (integer), effective-expiration-date (RFC 3339), include-subdomains (boolean), noted-hostname, served-certificate-chain (PEM array), validated-certificate-chain (PEM array), and known-pins (array of 'pin-<alg>="<base64>"' strings).
The pin-directive encodes a cryptographic identity as 'pin-<algorithm>=<base64-encoded-SPKI-fingerprint>'. The only currently allowed algorithm token is 'sha256'; the value is the base64-encoded SHA-256 hash of the DER-encoded SubjectPublicKeyInfo structure of an X.509 certificate.