HPKP Cheat Sheet

This page is a concise overview of all supported features and directives in HTTP Public Key Pinning. It can be used as a quick reference guide to identify valid and invalid directives and values, contains example policies and guidance on how to use HPKP effectively.


Directives - a list of all HPKP directives.

pin-sha256 | max-age | includeSubDomains | report-uri | preload


Directives

 

pin-sha256="[base64-value]";

This is the Base64 encoded version of the SHA256 hash of the SPKI of the public key being pinned.

 

max-age=[seconds];

This is the time, in seconds, that the browser should cache and apply the given HSTS policy for.

 

includeSubDomains;

This flag indicates that the browser should also apply this policy to all subdomains below the current domain.

 

report-uri="[URI]";

This directive instructs the browser to POST a JSON payload to the endpoint specified when a violation of the HPKP policy occurs.

 

preload;

This flag indicates that the site wishes to be included in the HPKP Preload list.


Example policies

Here are a few example policies ranging in purpose and strength:

To start out, sites should issue their HPKP policy in report only mode.

Public-Key-Pins-Report-Only: pin-sha256="[base64-value]"; pin-sha256="[base64-value]"; report-uri="https://report-uri.io"

This policy has no max-age directive so will not be cached and because of the Report-Only addition to the header name it will not take any blocking action. Instead, the browser will report any problem that would have occurred.



If there are no errors reported from the test deployment, you can enforce the header with a low max-age value.

Public-Key-Pins: pin-sha256="[base64-value]"; pin-sha256="[base64-value]"; report-uri="https://report-uri.io; max-age=600"

The low max-age means you can stop issuing the policy and it will expire quickly for those that have received it. After this the next step is to start increasing the max-age value.



You should aim for a max-age value of 60 days after making many, small incremental increases to test your ability to support HPKP.

Public-Key-Pins: pin-sha256="[base64-value]"; pin-sha256="[base64-value]"; report-uri="https://report-uri.io; max-age=5184000"

Remember, slowly increase the value of max-age over time.



Whether or not you use the includeSubDomains directive will depend on your particular use case.

Public-Key-Pins: pin-sha256="[base64-value]"; pin-sha256="[base64-value]"; report-uri="https://report-uri.io; max-age=5184000; includeSubDomains"

Using includeSubDomains is not always appropriate for HPKP.

Warning: I would not advise HPKP preloading other than for the most mature sites and operations/security team.


Chromium HSTS Preload List (contains HPKP preload info too):
https://cs.chromium.org/chromium/src/net/http/transport_security_state_static.json

Check HPKP header on Security Headers:
https://securityheaders.io

Guidance on setting up HPKP:
https://scotthelme.co.uk/guidance-on-setting-up-hpkp/

The HPKP toolset!:
https://scotthelme.co.uk/hpkp-toolset/

HPKP reporting:
https://scotthelme.co.uk/csp-and-hpkp-violation-reporting-with-report-uri-io/

Introduction to HPKP:
https://scotthelme.co.uk/hpkp-http-public-key-pinning/

Strict:
https://hlandau.github.io/draft-landau-websec-key-pinning-really/

Ivan Ristic - Is HTTP Public Key Pinning Dead?
https://blog.qualys.com/ssllabs/2016/09/06/is-http-public-key-pinning-dead



sources

HPKP RFC:
https://tools.ietf.org/html/rfc7469