Public Key Pinning
What is Public Key Pinning?
The HTTP Public Key Pinning (HPKP) security header, defined in RFC 7469, is used to tell a client to associate a particular public key to a specific web server. This security measure helps prevent man-in-the-middle (MITM) attacks in the event that an attacker compromises a certificate authority (CA) and starts issuing forged certificates. Public Key Pinning works in the following manner:
- Upon the first visit to an HTTPS-enabled website, the client receives an HTTP header which contains information about the web server certificate's public key.
- Upon subsequent visits, the client expects the same public key to be present in the certificate chain.
- If the previously known public key is not present, then the client should display a warning or send a report of a key mismatch.
With this method, the browser is able to tell if the public key from the origin server has changed and therefore avoid the risk of an attack.
Public Key Pins directives
When enabling the HPKP on your web server (which we'll explain how to do below), there are a few directives that can be defined. These include:
pin-sha256(mandatory) - Uses the SHA256 hash algorithm to specify the Base64 encoded Subject Public Key Information (SPKI) fingerprint.
max-age(mandatory) - The amount of time (in seconds) for which the web client should recognize the server as a known pinned host.
includeSubDomains(optional) - A valueless directive that tells the client that the SSL pinning policy applies to the server's subdomains as well.
report-uri(optional) - Provides you with the option to specify a URL for which any pin validation failures should be posted to.
Browser support for public key SSL pinning isn't complete yet. According to caniuse, currently three major browsers support the use of HPKP, these include: Chrome, Firefox, and Opera.
If the browser does not support public key pinning or it is the first time the browser is accessing a particular server, then the browser will accept the certificate as long as all basic checks are passed. Therefore, there is the risk of an attack if the website visitor is not using a web client which supports HPKP.
How to enable Public Key Pins
Depending upon which web server you are using, the process for enabling HPKP will be slightly different. However, each snippet below will ultimately render the same outcome - add the
Public-Key-Pins header to your HTTP responses. The snippets required for Apache and Nginx web servers are each outlined below.
The following snippet can be added to your Apache web server's configuration file. In order for this to work, you will need to have the
mod_headers module enabled.
Header set Public-Key-Pins "pin-sha256=\"base64+primary==\"; pin-sha256=\"base64+backup==\"; max-age=5184000; includeSubDomains"
The following is an example for Apache users with the placeholders filled in.
Header set Public-Key-Pins "pin-sha256=\"jkUohjD+18XbGoc3Jz5C9uC/HDyXoo4Q42ZnxArUuIM=\"; pin-sha256=\"V6V+CG2xiEkPR91kqtQp+RndQ39way8wKP8OP3IcZoA=\"; max-age=5184000; includeSubDomains"
The following snippet can be added to your Nginx server's configuration file. This requires that you have the ngx_http_headers_module enabled.
add_header Public-Key-Pins 'pin-sha256="base64+primary=="; pin-sha256="base64+backup=="; max-age=5184000; includeSubDomains' always;
With the placeholders filled in, the snippet should look similar to:
add_header Public-Key-Pins 'pin-sha256="jkUohjD+18XbGoc3Jz5C9uC/HDyXoo4Q42ZnxArUuIM="; pin-sha256="V6V+CG2xiEkPR91kqtQp+RndQ39way8wKP8OP3IcZoA="; max-age=5184000; includeSubDomains' always;
Using certificate pinning instead of HPKP
Another option that achieves the same end goal as public key pinning is known as certificate pinning. This method is more simple than public key pinning, however isn't as flexible. If you run an application that rotates its certificate regularly then it may be more convenient to use public key pinning. On the other hand, if the SSL certificate for your site or application is only updated every year or two, then it may be easier to simply compare the entire certificate rather than go through the process of extracting the public key from a certificate.
HPKP or SSL pinning is another great addition to your web server if you are looking to increase security for both you and your visitors. Implementation is quite straightforward and there should be minimal configurations required once the header is added. For more information regarding increasing your website's security, check out the following related articles.