Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


HTTP Public Key Pinning Extension (HPKP) for Apache, NGINX and Lighttpd
New on LowEndTalk? Please Register and read our Community Rules.

All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.

HTTP Public Key Pinning Extension (HPKP) for Apache, NGINX and Lighttpd

Public Key Pinning means that a certificate chain must include a whitelisted public key. It ensures only whitelisted Certificate Authorities (CA) can sign certificates for *.example.com, and not any CA in your browser store. This article has background theory and configuration examples for Apache, Lighttpd and NGINX.

HTTP Public Key Pinning Extension

An example might be your bank, which always have their certificate from CA Company A. With the current certificate system, CA Company B, CA Company C and the NSA CA can all create a certificate for your bank, which your browser will hapily accept because those companies are also trusted root CA's.

If the bank implements HPKP and pin's their first intermidiate certificate (from CA Company A), browsers will not accept certificates from CA Company B and CA Company C, even if they have a valid trust path. HPKP also allows your browser to report back the failure to the bank, so that they know they are under attack.

Public Key Pinning Extension for HTTP (HPKP) is a standard for public key pinning for HTTP user agents that's been in development since 2011. It was started by Google, which, even though it had implemented pinning in Chrome, understood that
manually maintaining a list of pinned sites can't scale.

Here is a quick feature overview of HPKP:

  • HPKP is set at the HTTP level, using the Public-Key-Pins response header.
  • The policy retention period is set with the max-age parameter, it specifies duration in seconds.
  • The PKP header can only be used over an error-free secure encryption.
  • If multiple headers are seen, only the first one is processed.
  • Pinning can be extended to subdomains with the includeSubDomains parameter.
  • When a new PKP header is received, it overwrites previously stored pins and metadata.
  • A pin consists out of the hashing algorithm and an "Subject Public Key Info" fingerprint.

This article first has some theory about the workings of HPKP, down below you'll find the part which shows you how to get the required fingerprints and has web server configuration.

SPKI Fingerprint - Theory

As explained by Adam Langley in his post, we hash a public key, not a certificate:

In general, hashing certificates is the obvious solution, but the wrong one. The problem is that CA certificates are often reissued: there are multiple certificates with the same public key, subject name etc but different extensions or expiry dates. Browsers build certificates chains from a pool of certificates, bottom up, and an alternative version of a certificate might be substituted for the one that you expect.

For example, StartSSL has two root certificates: one signed with SHA1 and the other with SHA256. If you wished to pin to StartSSL as your CA, which certificate hash would you use? You would have to use both, but how would you know about the other root if I hadn't just told you?

Conversely, public key hashes must be correct:

Browsers assume that the leaf certificate is fixed: it's always the starting point of the chain. The leaf certificate contains a signature which must be a valid signature, from its parent, for that certificate. That implies that the public key of the parent is fixed by the leaf certificate. So, inductively, the chain of public keys is fixed, modulo truncation.

The only sharp edge is that you mustn't pin to a cross-certifying root. For example, GoDaddy's root is signed by Valicert so that older clients, which don't recognise GoDaddy as a root, still trust those certificates. However, you wouldn't want to pin to Valicert because newer clients will stop their chain at GoDaddy.

>

Also, we're hashing the SubjectPublicKeyInfo not the public key bit string. The SPKI includes the type of the public key and some parameters along with the public key itself. This is important because just hashing the public key leaves one open to misinterpretation attacks. Consider a Diffie-Hellman public key: if one only hashes the public key, not the full SPKI, then an attacker can use the same public key but make the client interpret it in a different group. Likewise one could force an RSA key to be interpreted as a DSA key etc.

Where to Pin

Where should you pin? Pinning your own public key is not the best idea. The key might change or get compromised. You might have multiple certificates in use. The key might change because you rotate your certificates every so often. It might key compromised because the web server was hacked.

My take on it is that the best place to pin is the first intermediate CA certificate. The signature of that certificate is on your websites certificate so the issuing CA's public key must always be in the chain.

This way you can renew your end certificate from the same CA and have no pinning issues. If the CA issues a different root, then you have a problem, there is no clear solution for this yet. There is one thing you can do to mitigate this:

  • Always have a backup pin and a spare certificate from a different CA.

The RFC states that you need to provide at least two pins. One of the pins must be present in the chain used in the connection over which the pins were received, the other pin must not be present.

This other pin is your backup public key. It can also be the SPKI fingerprint of a different CA where you have a certificate issued.

SPKI Fingerprint

To get the SPKI fingerprint from a certificate we can use the following OpenSSL command, as shown in the RFC draft:

openssl x509 -noout -in certificate.pem -pubkey | \
openssl asn1parse -noout -inform pem -out public.key;
openssl dgst -sha256 -binary public.key | openssl enc -base64

Result:

klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=

The input certificate.pem file is the first certificate in the chain for this website. (At the time of writing, COMODO RSA Domain Validation Secure Server CA, Serial 2B:2E:6E:EA:D9:75:36:6C:14:8A:6E:DB:A3:7C:8C:07.)

You need to also do this with your backup public key, ending up with two fingerprints.

Webserver configuration

Read on over at https://raymii.org/s/articles/HTTP_Public_Key_Pinning_Extension_HPKP.html

Thanked by 3jar Blanoz mpkossen

Comments

  • gbshousegbshouse Member, Host Rep

    You might be interested in DANE/TLSA.

  • For back-up pins, IMO you are better off pinning a back-up CSR instead of a CA intermediate certificate. This will allow the flexibility of choosing another CA (other than Comodo as shown in the link above) when you need to get an emergency certificate issued.

    This python script is a much convenient method to get SPKI fingerprints too.
    https://github.com/StalkR/misc/blob/master/crypto/http_pins.py

  • @ranpha said:
    For back-up pins, IMO you are better off pinning a back-up CSR instead of a CA intermediate certificate. This will allow the flexibility of choosing another CA (other than Comodo as shown in the link above) when you need to get an emergency certificate issued.

    This python script is a much convenient method to get SPKI fingerprints too.
    https://github.com/StalkR/misc/blob/master/crypto/http_pins.py

    You are free to pin as many certs as you want, I give two as example because that is the minimum according to the RFC. The script hides much from the user, I hope that by linking the RFC and providing the actual suggested commands they read more about what they are doing and understand it better.

  • Yes I know there must be two pins at least. But pinning an intermediate CA is not exactly a better alternative to pinning a backup CSR. The CSR can be used with any CA, but pinning an intermediate CA means your emergency/backup certificate must come from them.

    The script is pretty much open source, anyone can examine it if they want to know how it works. Plus it can accept multiple certificates in one go and can output multiple keys in a single command.

Sign In or Register to comment.