HPKP best practices if you choose to implement

@pde I think to say it is inherently dangerous because the idea and the technical background is not dangerous, only if not correctly been used.
And personal i do not like to pin an CA. My personal hint is to create two backup spare keys.
One for RSA one for EC and pin these two backup keys currently not used and safe them offline.
(Maybe even print out as QR code for recovery).
Than you can change to any CA and nobody can push an unauthorized Cert to the user, not even an Good-CA acting on an NSL (National Security Letter).

2 Likes

same here that's what i do as well HTTP Public Key Pinning - HPKP for Centmin Mod Nginx SPDY / HTTP/2 but i am only testing with short max-age values for now out of the box at 7 days

Didn't really want to pin against other CAs, but I guess there's use case if you switch CA SSL certs. But currently, all my in use production Wildcard SSL certs are with 3yr expiries so wasn't any issue unlike 90 day expiries :slight_smile:

I have a few questions:

Just to be clear on exactly what the recommended set of keys to pin on is:
a) All of the CA’s root keys
b) All of the CA’s intermediate keys
c) Same as “a” and “b” for a secondary trusted CA
d) Same as “a” and “b” for a third trusted CA
e) A pair of backup keys which are kept secret and ideally offline - One RSA and one EC
f) Each leaf key that has been issued for as long as they are valid

Is this correct ? It seems a little excessive - Why are the second and third CAs needed if you have your own backup leaf keys ?

It looks like “b” and “f” are suggested as either / or, where “b” could be used if you don’t know what the leaf keys are going to be (For example, in a load balanced environment where each server generates it’s own key and doesn’t know about the other servers / keys) and “f” is a better choice if the leaf keys are managed separately ?

Do you have (Or plan to have) a public feed which can be used to subscribe to root or intermediate key changes ?

What is the advice on the pinning expiry ? The specification suggests to start at 60 days, but this looks to have been written when year-long certificates were the norm - What is the suggested expiry based on the 90 day expiry of LE’s leaf certificates ? Should the duration be set to the duration of the shortest certificate in-use ? I.e. If the leaf key is expected to be refreshed in 5 days, should 5 days be used for the pin ?

Not Correct ideally you pin exactly 3 or more Public Keys:

  1. The currently used public key of your certificate (more iff you have more than one certificate in use)
  2. pair of backup keys which are kept secret and ideally offline - One RSA and one EC (Also here can be more if you have different EC-Curves as backup)
    This guarantees that ONLY YOU can create accepted certificates.
    Even an NSL (National Security Letter) that force an CA to sign an malicious cert is not accepted since the PIN limits to your keys and not the ca keys.
    With these setup i would say you can pin >3 months.
1 Like

a) is not needed if you already do b) - it may even be disadvantageous.

Also not needed, because you already pin the intermediates.

Indeed a nice idea to also backup an EC one.

Because you maybe also loose access to your backup keys...
(or just create more than one backup leaf key and store each of them - securely - at a different place.

Yes and if you pin the intermediates you can follow these "long term" suggestions as the intermediates won't change in the nearer future.

If you only pin your current leaf cert then yes - theoretically.
However if you really only want to pin leaf certs you may better either only renew them (so you can use the cert pin longer than 90days) and(/or) already pre-generate (but obviously not sign them by LE) the certs you intent to use afterwards, so that you can switch them (and the according HPKP header) one by one without having problems.

Related:

(bottom line :wink: )


But generally the best suggestion IMHO is: Read about the implications of each way you can do, weight the risks up and decide by yourself what best suites you/your webserver/your visitors. This may depend on many factors.
A good article as a first read about HPKP was written by @ScottHelme:
Guidance on setting up HPKP

2 Likes

And your users will be faced with a big large "This certificate was signed by an untrusted issuer" error :question:

Thank you all. I always knew pinning was a minefiled, but the more I learn about it the more it seems like a minefield inside of another minefield !

@Osiris: This page shows how the HPKP validation failure errors look in various browsers:

Unless you’re asking asking how the the backup keys are trusted by browsers ? When you need to use them, you create a certificate signing request using your backup key and get that signed by a commercial CA such as Let’s Encrypt - The keys are generated and controlled by you, but the chain of trust still exists.

1 Like

Ah, thanks, that’s what he ment… I was thinking about keeping keys and what the heck should you do with them in the event of trouble? Play your own CA? That’s not gonna work now is it? But nooo, make a CSR and send it to another trusted CA, d’oh… :stuck_out_tongue: It’s late, time for sleep :wink:

I have a new blog coming on how I now use Let’s Encrypt and HPKP. I’m not using the LE client due to the problems with key rotation but there is a simple solution. I will update once it’s published.

As @rugk says, you need to make sure you fully understand HPKP before deploying it, much like any new feature I guess. Always deploy in report-only mode and I’d recommend implementing reporting (https://report-uri.io) and to test your policy thoroughly (https://report-uri.io/home/tools).

*Full disclosure, the linked site is my service.

4 Likes

I read elsewhere on the forum that clients don't trace the chain of signatures beyond the first trusted certificate. So if the intermediates are trusted by the client, it won't trace the chain to the root and therefore, the HPKP verification will fail if the intermediates aren't defined as valid.

From RFC 7469, section 2.6

To perform Pin Validation, the UA will compute the SPKI Fingerprints for each certificate in the Pinned Host's validated certificate chain, using each supported hash algorithm for each certificate. (As described in Section 2.4, certificates whose SPKI cannot be taken in isolation cannot be pinned.) The UA MUST ignore superfluous certificates in the chain that do not form part of the validating chain. The UA will then check that the set of these SPKI Fingerprints intersects the set of SPKI Fingerprints in that Pinned Host's Pinning Metadata. If there is set intersection, the UA continues with the connection as normal. Otherwise, the UA MUST treat this Pin Validation failure as a non-recoverable error. Any procedure that matches the results of this Pin Validation procedure is considered equivalent.

So the UA should check the whole chain, not just the first trusted certificate. Just one valid Pin is enough for the validation to succeed.

2 Likes

And this is the practice for all/most clients that support HPKP? (I hope it is)

Well, the source code for Chromium does state a lot of HashesIntersect calls :stuck_out_tongue: over a variable hashes… Not quite sure where that variable comes from though… Not yet anyway.

Ah, found something:

// PublicKeyPins contains a number of SubjectPublicKeyInfo hashes for a site.
// The validated certificate chain for the site must not include any of
// |excluded_hashes| and must include one or more of |required_hashes|.
struct PublicKeyPins {
  const char* const* required_hashes;
  const char* const* excluded_hashes;
};

Looks like they also check the whole validated chain indeed. According to the comment anyway :wink:

1 Like

@Osiris yes, the UA will check the whole chain against pinned keys, you can pin either at the leaf, intermediate or root level. Sites like Github currently pin at the root level ( https://report-uri.io/home/pkp_analyse/https%3A%2F%2Fgithub.com ) so that only those 2 certificate authorities can issue for their domain.

The browser will check every SPKI hash in the served chain against every cached pin, you only need 1 match for the connection to succeed.

I’ve written a few articles on HPKP if you’d like some further reading: https://scotthelme.co.uk/tag/hpkp/

2 Likes

Here’s the article I mentioned: https://scotthel.me/LE

7 Likes

Thanks for the write up Scott, I have stayed away from HPKP but after reading that I will take a non important domain of mine and play with HPKP for a while and see how it goes before I dare to venture into using it on anything important… if ever.

Thanks also for your super awesome https://securityheaders.io/ one of the most invaluable resources which I use uber frequently.

I was randomly scanning some “supposedly” super secure sites today just for fun, or shall I say, sites that should be secure and they all scored a miserable F, tested all of them on Qualsys SSL Labs too and found so many that failed there too … bloody scary … some real idiots out there who get paid fat salaries and do not seem to know diddly about security and these are banks, government sites and online shopping sites I was testing.

My guess is that those “F” sites still do all to allow customers running Windowx XP and to do so still accept RC4 (aka. clear text)

accepting XP does not correlate to RC4, XP runs fine with 3DES which is iirc still more or less secure.

No, you can just have the public key signed by any CA whenever you decide to and the advantage is, that even if these keys are stolen, they are unusable before they certificate is issued.

However, this is not entirely correct. You should always also include a key, that you plan on using after your key expires. Changing key after it expires will look to browsers as an attack, so if you don’t have an additional key added, you will be forced to reuse your key, which is a terrible security practice.