Class HpkpHeaderWriter

  • All Implemented Interfaces:
    HeaderWriter

    public final class HpkpHeaderWriter
    extends java.lang.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
      HpkpHeaderWriter()
      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

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void addSha256Pins​(java.lang.String... pins)
      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 setPins​(java.util.Map<java.lang.String,​java.lang.String> pins)
      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​(java.lang.String reportUri)
      Sets the URI to which the browser should report pin validation failures.
      void setReportUri​(java.net.URI reportUri)
      Sets the URI to which the browser should report pin validation failures.
      void writeHeaders​(javax.servlet.http.HttpServletRequest request, javax.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 Detail

      • HpkpHeaderWriter

        public HpkpHeaderWriter​(long maxAgeInSeconds)
        Creates a new instance
        Parameters:
        maxAgeInSeconds - maps to setMaxAgeInSeconds(long)
      • HpkpHeaderWriter

        public HpkpHeaderWriter()
        Creates a new instance
    • Method Detail

      • writeHeaders

        public void writeHeaders​(javax.servlet.http.HttpServletRequest request,
                                 javax.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​(java.util.Map<java.lang.String,​java.lang.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:
        java.lang.IllegalArgumentException - if pins is null
      • addSha256Pins

        public void addSha256Pins​(java.lang.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:
        java.lang.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:
        java.lang.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​(java.net.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​(java.lang.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:
        java.lang.IllegalArgumentException - if the reportUri is not a valid URI