public final class HpkpHeaderWriter extends Object implements HeaderWriter
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 -base64The 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="http://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
Constructor and 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
|
Modifier and Type | Method and Description |
---|---|
void |
addSha256Pins(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(Map<String,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(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(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
Create a
Header instance. |
public HpkpHeaderWriter(long maxAgeInSeconds, boolean includeSubDomains, boolean reportOnly)
maxAgeInSeconds
- maps to setMaxAgeInSeconds(long)
includeSubDomains
- maps to setIncludeSubDomains(boolean)
reportOnly
- maps to setReportOnly(boolean)
public HpkpHeaderWriter(long maxAgeInSeconds, boolean includeSubDomains)
maxAgeInSeconds
- maps to setMaxAgeInSeconds(long)
includeSubDomains
- maps to setIncludeSubDomains(boolean)
public HpkpHeaderWriter(long maxAgeInSeconds)
maxAgeInSeconds
- maps to setMaxAgeInSeconds(long)
public HpkpHeaderWriter()
public void writeHeaders(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
HeaderWriter
Header
instance.writeHeaders
in interface HeaderWriter
request
- the requestresponse
- the responsepublic 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");
pins
- the map of base64-encoded SPKI fingerprint & cryptographic hash algorithm pairs.IllegalArgumentException
- if pins is nullpublic 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=");
pins
- a list of base64-encoded SPKI fingerprints.IllegalArgumentException
- if a pin is nullpublic 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));
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)IllegalArgumentException
- if maxAgeInSeconds is negativepublic 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.
includeSubDomains
- true to include subdomains, else falsepublic 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.
reportOnly
- true to report only, else falsepublic 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"));
reportUri
- the URI where the browser should send the report to.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");
reportUri
- the URI where the browser should send the report to.IllegalArgumentException
- if the reportUri is not a valid URI