On Friday, Chris Palmer announced the intent to deprecate HTTP Public Key Pinning (HPKP) in Chrome and remove the feature entirely in future. In this post, we’ll look at the problems with public key pinning, and how Certificate Transparency has become the more favoured method of avoiding maliciously issued certificates.
Public Key Pinning allows a web server to specify to the browser the acceptable public keys used to sign the certificates used initiate a TLS connection. This protects against the attack vector whereby a Certificate Authority (CA) is compromised and used to create certificates for a website maliciously, using different public keys than the ones specified by the website operator.
TLS aims to ensure authenticity and confidentiality. HPKP improves authenticity since we’re no longer reliant only on the CA to vouch for the website operator’s public key. In doing so it protects against man-in-the-middle attacks on the network (which would compromise confidentiality). With HPKP, the malicious certificate issuer would need to steal the website operator’s private keys too (which isn’t impossible, of course).
On the surface, this sounds like a great idea. But it has tricky consequences if you mess up. If you specify the wrong keys in your HPKP header, users will be unable to establish a new secure connection to your website until the pinned keys have expired. In the example below, this key will be pinned for 24 hours.
Public-Key-Pins: pin-sha256="key fingerprint"; max-age=86400,
The consequences of messing up aren’t a strong enough reason to discard HPKP altogether— after all, there are many ways you can deny service to users by misconfiguration. But larger worries stem from the complexity in how CAs and browser vendors build and verify trust chains.
So far we’ve only discussed pinning the website operator’s keys (present in the “leaf” certificate presented to the browser), but HPKP allows you to specify keys that are present anywhere in the trust chain, including those of root and intermediate CAs.
This provides stronger guarantees for the website operator. For instance, Github pins two root authorities (thanks to Scott Helme for the excellent analysis tool). One is presumably a backup.
On the subject of backups, Scott has written a great article on how to manage revocation and expiry while using public key pinning.
Verifying the trust chain from leaf certificate back to the root CA is complex. There may be differences in browser trust stores and how intermediate certificates are used to build the trust chain. As Chris Palmer notes in his announcement to blink-dev, this complexity translates into difficulty choosing a valid key set to pin to.
If HPKP isn’t an acceptable solution to avoiding certificate mis-issuance, what is? If you’ve been following this general topic, you’ve probably heard of Certificate Transparency, or CT.
The idea behind CT is that when a certificate is issued, it’s submitted to a publicly auditable log (usually by the CA itself, but it can be done by the website operator). CT logs are append-only and cryptographically verified — using a Merkle tree, just like your favourite blockchain. They can be run by anyone — even behind the sofa — although in practice they’re likely to be run by large companies with the resources to operate them.
Submitting a certificate to a CT log during issuance returns a Signed Certificate Timestamp (SCT) which is basically a promise that the certificate will be added to the public log. During a TLS handshake, the SCT is supplied by the web server and the browser uses this to verify that the certificate was properly issued. (This is an extremely simplified explanation of CT; I’d strongly recommend you read the design document).
A key advantage (sorry for the pun) of CT over HPKP is that verification happens at the level of granularity of a certificate (and its associated trust chain), not a public key. Although it requires more supporting infrastructure than public key pinning, the added flexibility of CT alleviates the burden on website operators to exhaustively specify their trust chain.
In readiness for Certificate Transparency, site operators can use the Expect-CT header to specify that the client should expect an SCT from their website, and initially report any errors without impacting usage. The proposed date for adoption in Chrome is April 2018.
Hopefully this was a useful overview of the tradeoffs between public key pinning and certificate transparency. I’m also on twitter, where I try to post intelligent things from time to time.