HTTP Public Key Pinning: When You Need Extra Trust

Imagine you build a house with the best locks money can buy. Then someone figures out a way to make copies of the master key without you knowing. That is the problem with the certificate authority system. Certificate authorities are supposed to be trustworthy. They are supposed to verify that a website belongs to who they say it does. But sometimes they get hacked. Sometimes they make mistakes. Sometimes they are forced to issue certificates they should not issue.

HTTP Public Key Pinning, or HPKP, is your way of saying to browsers: I only trust these specific keys for my website. Everything else, no matter who signed it, gets rejected. It is a powerful tool, but like any powerful tool, it can hurt you if you use it wrong.

What Problem Does HPKP Solve?

The certificate authority system works on trust. There are over a hundred organizations around the world that can issue certificates. If any one of them gets compromised, or if someone tricks them into issuing a fake certificate for your domain, that fake certificate would be accepted by browsers. An attacker could then run a site that looks exactly like yours, with a valid certificate, and intercept traffic from your users.

This has happened before. A few years back, a certificate authority called DigiNotar got hacked. Attackers issued dozens of fake certificates for major websites, including Google and Facebook. The fake certificates worked. Browsers trusted them because they came from a trusted authority. It took days before the industry caught on and started blocking those certificates.

HPKP stops this from working. Even if an attacker gets a fake certificate from a trusted authority, the browser will check the public key pins. If the key does not match the ones you told it to expect, the connection gets blocked. The attack fails.

How Pinning Actually Works

When a browser visits your site over HTTPS and sees the HPKP header, it remembers the pins you set. The next time someone visits, the browser checks the certificate against those pins. If the certificate does not contain one of the pinned keys anywhere in its chain, the browser refuses to connect. It shows a security error and does not let the user proceed.

You can pin the public key of your own certificate. You can also pin the public key of an intermediate certificate or the root certificate that issued yours. Pinning an intermediate or root means you do not have to change the pins every time you renew your certificate, as long as you use the same issuing chain.

The header looks something like this:

Public-Key-Pins: pin-sha256="base64=="; pin-sha256="another-base64=="; max-age=2592000; includeSubDomains

The pin-sha256 values are base64-encoded hashes of your public keys. You generate them from your certificate files. The max-age tells the browser how long to remember these pins, in seconds. A month is 2592000 seconds. Six months is about 15780000. You can also include subdomains if you want the pins to apply there as well.

Before You Even Think About Pinning

I have seen people implement HPKP without thinking it through, and then lock themselves out of their own sites. This is not something to experiment with on a live site without a clear plan. The browser remembers the pins. If you lose access to the private keys that match those pins, your users will not be able to reach your site until the pins expire. That can be months.

Before you deploy HPKP, you need a backup plan. The standard recommendation is to pin at least two keys. One is your current key. The other is a backup key that you keep somewhere safe, offline. If you need to switch to a new certificate, you can use that backup key. The backup key should be from a different certificate, preferably one that is not yet in use.

You also need to be confident that your certificate renewal process is solid. If your certificate expires and you cannot get a new one that matches the pins, your site becomes inaccessible to anyone who has the pins cached. That is a bad day for everyone involved.

Starting Small with Report-Only Mode

HPKP has a report-only mode that lets you test without breaking anything. Instead of the regular header, you use Public-Key-Pins-Report-Only. This header tells browsers to check the pins and send reports if they would have blocked the connection, but it does not actually block anything. You can run this for a while and see if any legitimate visitors would have been locked out.

The reports go to a URL you specify in the header. Setting up a reporting endpoint takes some work, but services like Report-URI can handle it for you. They collect the reports and show you what is happening. You can see if any of your users are hitting pin mismatches, and figure out why before you turn on enforcement.

I recommend running in report-only mode for at least a few weeks. Look at the data. Make sure you understand any mismatches that show up. Sometimes they happen because someone is using an old or different certificate chain. Sometimes they happen because you forgot to pin the right keys. Better to catch these things in report-only mode than to find out after enforcement is turned on.

Choosing Which Keys to Pin

Deciding what to pin is important. You can pin your leaf certificate, but that means you have to update your pins every time you renew or replace that certificate. That is doable but requires careful coordination. If you update your certificate without updating the pins at the same time, visitors who have the old pins cached will get blocked.

Pinning an intermediate certificate or a root certificate is more flexible. If you always get your certificates from the same issuer, you can pin that issuer's key. Then when you renew your certificate, the new one still has the same intermediate key in its chain. The pins still match. You do not have to change anything.

There is a tradeoff, though. If you pin an intermediate or root, and that key gets compromised, your pins are no longer protecting you against that specific compromise. But if that key is compromised, you have bigger problems anyway. Most sites do fine with pinning their intermediate certificate key.

Setting the Right Max-Age

The max-age value controls how long browsers remember your pins. Short durations mean less risk if something goes wrong. But they also mean less protection because visitors might not have the pins cached when they need them. Long durations give stronger protection but make mistakes more painful.

Many people start with a short max-age, like a few days or a week, while they make sure everything works. Once they are confident, they increase it. A common final value is 60 days or 90 days. Some sites go longer, up to a year. Going beyond that is risky because if you mess up, you are locked out for a very long time.

Remember that you can update the pins before the max-age expires. The browser stores the pins it sees most recently. If you send a new header with new pins, browsers that see it will update their cache. So you are not locked into your first set of pins forever. You can change them as long as you still have a valid certificate that matches the old pins while the new ones are being distributed.

Common Mistakes to Avoid

The biggest mistake I have seen is pinning only one key. If you only pin your current key and something happens to it, you have no way to recover. Always pin at least two keys. The second key is your backup. Store it somewhere safe. Do not use it for anything else until you need it.

Another mistake is forgetting about subdomains. If you set includeSubDomains, your pins apply to every subdomain. That might be what you want, or it might not. If you have subdomains that use different certificates from different issuers, they will break. Test this carefully before turning on enforcement.

I have also seen people implement HPKP without proper monitoring. If you do not have a way to see report-only data, you are flying blind. You will not know if your pins are causing problems until it is too late. Set up reporting first. Look at the data. Understand what is happening before you enforce anything.

Is HPKP Still Relevant?

There has been some debate about HPKP in recent years. Some browsers have removed support or are considering it. The idea behind pinning is still good, but the implementation has challenges. It is hard to do right. When done wrong, it locks people out of sites. Support across browsers is not as universal as it once was.

That said, for sites that need strong protection against rogue certificate authorities, HPKP still has value. It adds a layer of defense that nothing else provides. If your site handles highly sensitive data, or if you are worried about state-level attackers, pinning is worth considering.

For most sites, the effort and risk might not be worth it. Properly configured TLS with HSTS already gives you good protection. Adding pinning is an extra step for situations where the risk profile justifies it.

Testing Your Setup

Before you go live with HPKP, test everything in a controlled environment. Use report-only mode first. Verify that your pins are correct. Use the Qualys SSL Labs test to check your HPKP configuration. It will tell you if your pins are valid and if your backup key is set up properly.

You can also use browser developer tools to see if the header is being sent correctly. Open the network tab, reload your page, and look at the response headers. Make sure the header name is spelled right. Check that the pin values look correct.

If you use a content delivery network or a reverse proxy, make sure it is passing your HPKP headers. Some services strip or modify headers. You need to know what is actually reaching the browser.

Moving Forward with Caution

Public key pinning is not something to rush into. It requires planning, testing, and ongoing attention. If you decide to implement it, start with a short max-age in report-only mode. Watch the reports. Make sure everything works. Then gradually increase the max-age and eventually switch to enforcement.

Keep your backup key safe. Document where it is and how to use it. Make sure more than one person knows about it. If you leave the company and no one else knows about the backup key, that key might as well not exist.

Remember that HPKP is a tool for specific situations. It is not required for every site. Evaluate whether you actually need it. If you do, take the time to do it right. A bad pinning implementation is worse than no pinning at all.