Enable the HTTP public key fixed extension tutorial on the server

  • 2020-05-13 04:11:45
  • OfStack

Public key fixed (Public Key Pinning) means that a certificate chain must contain a public key in a whitelist, which means that only a whitelist certificate issuing authority (CA) can issue a certificate for a domain name *.example.com, not any CA stored in your browser. This article describes the background to this mechanism and provides configuration examples on Apache, Lighttpd, and NGINX.
HTTP public key fixed extension

Take your bank, which USES CA A to issue certificates. However, under the current certificate system, CA B, CA C and CA NSA can all create certificates for your bank, and your browser will accept them without any doubt, because these companies are the root CA that you trust.

If your bank implements HPKP and fixes their first intermediate certificate (from CA A), then the browser will not accept certificates from CA B and CA C, even though they have a valid trust chain. HPKP also allows your browser to report this violation to the bank so that the bank knows it has been attacked with a fake certificate.

The HTTP public key fixing extension is a public key fixing standard for HTTP user agents (browsers) that has been developed since 2011. It was initiated by Google, and even the fixed mechanism implemented in Chrome can use a manually maintained list of web site public keys containing the fixed public key signatures of several web sites. Both Chrome and FireFox 32 and later support public key fixation and use built-in, manually maintained public key fixation list data that is updated as the browser software is updated, mainly for several large sites. Currently, only Chrome 38+ supports the transfer of public key fixed information through HTTP response headers.

The following is a brief overview of several features of HPKP:

HPKP is set at the HTTP level, using the Public-Key-Pins (PKP) response header. The retention period for this rule is set by the max-age parameter in seconds. The PKP response header can only be used inside the correct secure encrypted communication. If more than one of these response headers occurs, only the first is processed. The fixed mechanism can be extended to subdomains using the includeSubDomains parameter. When a new PKP response header is received, it overrides the previously stored public key fixation and metadata. Public key fixation is generated by hash algorithm, which is actually a "subject public key information (SKPI)" fingerprint.

In this article, we will first explain how HPKP works, and then we will show you how to get the required fingerprint and configure it to web server.
SPKI fingerprints - theory

In general, hashing a certificate is an obvious solution, but it's not. The reason why this is not possible is that the CA certificates can be continually reissued: the same public key and subject name can correspond to multiple certificates with different times of extension or expiration. When the browser builds the certificate chain from the bottom up in the certificate pool, another version of the certificate may instead match the certificate you expected.

For example, StartSSL has two root certificates: one signed with SHA1 and one signed with SHA256. If you want to pin StartSSL as your CA, which certificate should you use? You might be able to use both of these, but if I don't tell you, how will you know there's still a root certificate?

Hash the public key, on the other hand, does not have this problem:

The browser fake stator certificate is fixed: it is always the starting point of the certificate chain. The signature 1 carried by the child certificate must be a valid signature from the parent certificate issued specifically for the certificate. That is, the public key of the parent certificate is fixed relative to the child certificate. So it can be inferred that the chain of public keys is fixed.

The problem with only 1 is that you can't pin it to a cross-certified root certificate. For example, the root certificate of GoDaddy is signed by Valicert, so that old customers who cannot recognize the GoDaddy root certificate can trust their certificate. However, you can't pin it to Valicert because a new customer finds an GoDaddy certificate on the certificate chain and it stops going up the chain.

In addition, we hash SubjectPublicKeyInfo (SPKI) rather than the public key bit string. SPKI includes the public key type, the public key itself and its related parameters. This is important because hashing the public key can lead to a distortion attack. For one Diffie-Hellman public key: if you hash only the public key, not the full SPKI, then the attacker can use the same public key and have the client interpret it as another group. Similarly, it is possible to force an RSA key to be interpreted as an DSA key, and so on.

Fix where

Where should you be fixed? Fixing your own public key is not the best way to do it. Your key may be changed or revoked. You may be using multiple certificates, and the key will change if you rotate the certificates frequently. Perhaps the certificate was revoked because the server was hacked.

The easiest, but not too safe, way to do this is to fix the first intermediate CA certificate. The certificate is signed on top of your web site certificate, so the CA public key that issued the certificate must be on the certificate chain.

In this way you can update your certificate from the same CA without worrying about the fixed information being incorrect. If the CA issues a different root certificate, you may have some problems that you don't have a good solution for. However, you can mitigate the impact of this problem by:

Apply for a backup certificate from a different CA and secure the backup.

RFC says you need to do at least two fixes. One is on the certificate chain used for the current connection, and the other is a backup.

The other fixation is on the backup public key, which can be an SKPI fingerprint from a different CA that issued you the certificate.

A safer way to do this is to create at least three separate public keys (using OpenSSL, see this page for the Javascript OpenSSL command generator) and backup two of them to a secure location, stored offline, not on the web.

Create the SPKI fingerprint for the three certificates and fix them, then use only the first as the current certificate. You can use backup key 1 when needed. But you need to have CA sign you to generate the certificate yes, it may take a few days, depending on how your CA works.

This is fine for HPKP, because we are using the SPKI hash of the public key, not the certificate. Invalidated or different CA signature chains are not affected.

If you generate and securely store at least three separate keys as described above and secure them, you can also prevent problems when your CA revoks your website certificate and issues a fake certificate.
SPKI fingerprint

The SPKI fingerprint can be generated using the following OpenSSL command, which appears 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

Results:

klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=

Input above certificate pem file is this site (https: / / raymii org) of the first certificate in the certificate chain. (when writing this article, COMODO RSA Domain Validation Secure Server CA, serial number 2 B: 2 E: 6 E: EA: D9:75: thing C: o A: 6 E: DB: A3:7 C: 8 C: 07).

You will also need to generate fingerprints for your other two backup public keys.
The fault

At the time of writing this article (2015/1), only 1 browser (chrome) that supports HPKP has a serious problem: Chrome cannot distinguish the max-age and includeSubdomains parameters in the HSTS and HPKP response headers. That is, if your HSTS and HPKP set different max-age and includeSubdomains parameters, they will mess with each other. More information about the fault see: https: / / code google. com p/chromium issues/detail & # 63; id = 444511. Thank Scott Helme (https: / / scotthelme. co. uk) found and told me the Chromium project problems.
Web server configuration

Below you can see the three main Web server configuration methods. This is just one HTTP response header, which can be set on most Web servers. It just needs to be set up on the HTTPS website.

The following example is fixed to COMODO RSA Domain Validation Secure Server CA and the backup Comodo PositiveSSL CA, with a 30-day period of failure, including all subdomains.
Apache

Edit your Apache configuration files (such as/etc/apache2 / sites - enabled/website conf or/etc apache2 / httpd conf), and add the following line to your VirtualHost:

#  Load as needed  headers  The module. 
    LoadModule headers_module modules/mod_headers.so
    Header set Public-Key-Pins "pin-sha256=\"klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=\"; pin-sha256=\"633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q=\"; max-age=2592000; includeSubDomains"

Lighttpd

Lighttpd more simple 1, add the following line to your Lighttpd configuration files (such as/etc lighttpd/lighttpd. conf) :

server.modules += ( "mod_setenv" )
    $HTTP["scheme"] == "https" {
        setenv.add-response-header  = ( "Public-Key-Pins" => "pin-sha256=\"klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=\"; pin-sha256=\"633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q=\"; max-age=2592000; includeSubDomains")
    }

NGINX

The configuration of NGINX is even shorter. Add the following lines to the server block in your HTTPS configuration:

add_header Public-Key-Pins 'pin-sha256="klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY="; pin-sha256="633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q="; max-age=2592000; includeSubDomains';

Reporting capabilities

The HPKP reporting feature allows the browser to report any violations to you.

If you are in the response headers added additional report - uri = "http: / / example org/hpkp - report" parameter, and used the URI processing the received data, the client will send report to you when the discovery of violations. This report is sent to your designated report-uri in POST format similar to JSON below:

{
        "date-time": "2014-12-26T11:52:10Z",
        "hostname": "www.example.org",
        "port": 443,
        "effective-expiration-date": "2014-12-31T12:59:59",
        "include-subdomains": true,
        "served-certificate-chain": [
            "-----BEGINCERTIFICATE-----\nMIIAuyg[...]tqU0CkVDNx\n-----ENDCERTIFICATE-----"
        ],
        "validated-certificate-chain": [
            "-----BEGINCERTIFICATE-----\nEBDCCygAwIBA[...]PX4WecNx\n-----ENDCERTIFICATE-----"
        ],
        "known-pins": [
            "pin-sha256=\"dUezRu9zOECb901Md727xWltNsj0e6qzGk\"",
            "pin-sha256=\"E9CqVKB9+xZ9INDbd+2eRQozqbQ2yXLYc\""
        ]
    }

Not mandatory, report only

HPKP can also be set to non-mandatory, using Public-Key-Pins-Report-Only to send only violation reports to you.

This allows you to be flexible if the site is not accessible or if the HPKP configuration is incorrect. You can then change the response header to Public-Key-Pins to force the fix.


Related articles: