Class HpkpHeaderWriter

java.lang.Object
org.springframework.security.web.header.writers.HpkpHeaderWriter
All Implemented Interfaces:
HeaderWriter

public final class HpkpHeaderWriter extends Object implements HeaderWriter
Provides support for HTTP Public Key Pinning (HPKP).

Since Section 4.1 states that a value on the order of 60 days (5,184,000 seconds) may be considered a good balance, we use this value as the default. This can be customized using setMaxAgeInSeconds(long).

Because Appendix B recommends that operators should first deploy public key pinning by using the report-only mode, we opted to use this mode as default. This can be customized using setReportOnly(boolean).

Since we need to validate a certificate chain, the "Public-Key-Pins" or "Public-Key-Pins-Report-Only" header will only be added when ServletRequest.isSecure() returns true.

To set the pins you first need to extract the public key information from your certificate or key file and encode them using Base64. The following commands will help you extract the Base64 encoded information from a key file, a certificate signing request, or a certificate.

 openssl rsa -in my-key-file.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

 openssl req -in my-signing-request.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

 openssl x509 -in my-certificate.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
 
The following command will extract the Base64 encoded information for a website.
 openssl s_client -servername www.example.com -connect www.example.com:443 | openssl x509 -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
 

Some examples:

 Public-Key-Pins: max-age=3000;
                pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=";
                pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="

 Public-Key-Pins: max-age=5184000;
                pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
                pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="

 Public-Key-Pins: max-age=5184000;
                pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
                pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=";
                report-uri="https://example.com/pkp-report"

 Public-Key-Pins-Report-Only: max-age=5184000;
                pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
                pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=";
                report-uri="https://other.example.net/pkp-report"

 Public-Key-Pins: max-age=5184000;
                pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=";
                pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
                pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=";
                includeSubDomains
 

Since:
4.1
  • Constructor Summary

    Constructors
    Constructor
    Description
    Creates a new instance
    HpkpHeaderWriter(long maxAgeInSeconds)
    Creates a new instance
    HpkpHeaderWriter(long maxAgeInSeconds, boolean includeSubDomains)
    Creates a new instance
    HpkpHeaderWriter(long maxAgeInSeconds, boolean includeSubDomains, boolean reportOnly)
    Creates a new instance
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Adds a list of SHA256 hashed pins for the pin- directive of the Public-Key-Pins header.
    void
    setIncludeSubDomains(boolean includeSubDomains)
    If true, the pinning policy applies to this pinned host as well as any subdomains of the host's domain name.
    void
    setMaxAgeInSeconds(long maxAgeInSeconds)
    Sets the value (in seconds) for the max-age directive of the Public-Key-Pins header.
    void
    Sets the value for the pin- directive of the Public-Key-Pins header.
    void
    setReportOnly(boolean reportOnly)
    To get a Public-Key-Pins header you should set this to false, otherwise the header will be Public-Key-Pins-Report-Only.
    void
    setReportUri(String reportUri)
    Sets the URI to which the browser should report pin validation failures.
    void
    setReportUri(URI reportUri)
    Sets the URI to which the browser should report pin validation failures.
    void
    writeHeaders(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response)
    Create a Header instance.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

  • Method Details

    • writeHeaders

      public void writeHeaders(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response)
      Description copied from interface: HeaderWriter
      Create a Header instance.
      Specified by:
      writeHeaders in interface HeaderWriter
      Parameters:
      request - the request
      response - the response
    • setPins

      public void setPins(Map<String,String> pins)

      Sets the value for the pin- directive of the Public-Key-Pins header.

      The pin directive specifies a way for web host operators to indicate a cryptographic identity that should be bound to a given web host. See Section 2.1.1 for additional details.

      To get a pin of Public-Key-Pins: pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" Use Map<String, String> pins = new HashMap<String, String>(); pins.put("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=", "sha256"); pins.put("E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=", "sha256");

      Parameters:
      pins - the map of base64-encoded SPKI fingerprint & cryptographic hash algorithm pairs.
      Throws:
      IllegalArgumentException - if pins is null
    • addSha256Pins

      public void addSha256Pins(String... pins)

      Adds a list of SHA256 hashed pins for the pin- directive of the Public-Key-Pins header.

      The pin directive specifies a way for web host operators to indicate a cryptographic identity that should be bound to a given web host. See Section 2.1.1 for additional details.

      To get a pin of Public-Key-Pins-Report-Only: pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" Use HpkpHeaderWriter hpkpHeaderWriter = new HpkpHeaderWriter(); hpkpHeaderWriter.addSha256Pins("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM", "E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=");

      Parameters:
      pins - a list of base64-encoded SPKI fingerprints.
      Throws:
      IllegalArgumentException - if a pin is null
    • setMaxAgeInSeconds

      public void setMaxAgeInSeconds(long maxAgeInSeconds)

      Sets the value (in seconds) for the max-age directive of the Public-Key-Pins header. The default is 60 days.

      This instructs browsers how long they should regard the host (from whom the message was received) as a known pinned host. See Section 2.1.2 for additional details.

      To get a header like Public-Key-Pins-Report-Only: max-age=2592000; pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" Use HpkpHeaderWriter hpkpHeaderWriter = new HpkpHeaderWriter(); hpkpHeaderWriter.setMaxAgeInSeconds(TimeUnit.DAYS.toSeconds(30));

      Parameters:
      maxAgeInSeconds - the maximum amount of time (in seconds) to regard the host as a known pinned host. (i.e. TimeUnit.DAYS.toSeconds(30) would set this to 30 days)
      Throws:
      IllegalArgumentException - if maxAgeInSeconds is negative
    • setIncludeSubDomains

      public void setIncludeSubDomains(boolean includeSubDomains)

      If true, the pinning policy applies to this pinned host as well as any subdomains of the host's domain name. The default is false.

      See Section 2.1.3 for additional details.

      To get a header like Public-Key-Pins-Report-Only: max-age=5184000; pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="; includeSubDomains you should set this to true.

      Parameters:
      includeSubDomains - true to include subdomains, else false
    • setReportOnly

      public void setReportOnly(boolean reportOnly)

      To get a Public-Key-Pins header you should set this to false, otherwise the header will be Public-Key-Pins-Report-Only. When in report-only mode, the browser should not terminate the connection with the server. By default this is true.

      See Section 2.1 for additional details.

      To get a header like Public-Key-Pins: max-age=5184000; pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" you should the this to false.

      Parameters:
      reportOnly - true to report only, else false
    • setReportUri

      public void setReportUri(URI reportUri)

      Sets the URI to which the browser should report pin validation failures.

      See Section 2.1.4 for additional details.

      To get a header like Public-Key-Pins-Report-Only: max-age=5184000; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="; pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="; report-uri="https://other.example.net/pkp-report" Use HpkpHeaderWriter hpkpHeaderWriter = new HpkpHeaderWriter(); hpkpHeaderWriter.setReportUri(new URI("https://other.example.net/pkp-report"));

      Parameters:
      reportUri - the URI where the browser should send the report to.
    • setReportUri

      public void setReportUri(String reportUri)

      Sets the URI to which the browser should report pin validation failures.

      See Section 2.1.4 for additional details.

      To get a header like Public-Key-Pins-Report-Only: max-age=5184000; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="; pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="; report-uri="https://other.example.net/pkp-report" Use HpkpHeaderWriter hpkpHeaderWriter = new HpkpHeaderWriter(); hpkpHeaderWriter.setReportUri("https://other.example.net/pkp-report");

      Parameters:
      reportUri - the URI where the browser should send the report to.
      Throws:
      IllegalArgumentException - if the reportUri is not a valid URI