title: Tomcat filter for enabling HPKP
body: <p>I am trying to enable HPKP certificate pinning in our app's tomcat server. I added a filter to include the HSTS and HPKP directives. I am getting the HSTS and HPKP directives in the response header as expected. </p>
  
  <p>But even after I change the certificate in the server or intercept the request and send a fake certificate, browser does not stop the request. Browser is HPKP capable as it is blocking other HPKP enabled sites like facebook when the request is intercepted and presented with a fake certificate. </p>
  
  <p>Just wondering if there is anything wrong the way I am generating the hash of the public key and hence browser is not pinning the key? Any feed back if anyone has enabled HPKP for tomcat?</p>
  
  <p>Filter added in web.xml</p>
  
  <pre><code>    &lt;filter&gt;
              &lt;filter-name&gt;HttpsSecFilter&lt;/filter-name&gt;
              &lt;filter-class&gt;com.x.x.x.x.x.HttpsSecurityFilter&lt;/filter-class&gt;
      &lt;/filter&gt;
      &lt;filter-mapping&gt;
              &lt;filter-name&gt;HttpsSecFilter&lt;/filter-name&gt;
              &lt;url-pattern&gt;..[url-pattern]..&lt;/url-pattern&gt;
      &lt;/filter-mapping&gt;
  </code></pre>
  
  <p>Filter code (Modified to include only relevant parts for brevity)</p>
  
  <pre><code>public class HttpsSecurityFilter implements Filter {
      private boolean _isHTTSEnabled = false;
      private long _httsMaxAge = -1;
  
      private boolean _isHPKPEnabled = false;
      private long _hpkpMaxAge = -1;
      private String _hpkpCertHashesString = null;
  
      private boolean _includeSubdomains = false;
  
      @Override
      public void destroy() {
      }
  
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, 
                  FilterChain chain) throws IOException, ServletException {
  
          if (_isHTTSEnabled &amp;&amp; response instanceof HttpServletResponse) {
              ((HttpServletResponse) response).setHeader("Strict-Transport-Security", 
                                                         "max-age=" + _httsMaxAge);
          }
  
          if (_isHPKPEnabled &amp;&amp; response instanceof HttpServletResponse) {
              ((HttpServletResponse) response).setHeader("Public-Key-Pins", 
                                                         _hpkpCertHashesString);
          }
  
          chain.doFilter(request, response);
      }
  
      @Override
      public void init(FilterConfig arg0) throws ServletException {
          //Read from application configuration file
          _isHTTSEnabled = true;
          _httsMaxAge = 5184000;
  
          _isHPKPEnabled = true;
          _hpkpMaxAge = 5184000;
          _includeSubdomains = false;
  
          if (_isHTTSEnabled) {
  
              try {
                  KeyStore keyStore = KeyStore.getInstance("JKS");
                  InputStream is = new FileInputStream(APP_HOME + "/conf/keystore");
                  keyStore.load(is, keysotrePassword);
                  is.close();
  
                  Certificate cert = keyStore.getCertificate(myappcetificatealias);
  
                  MessageDigest md = MessageDigest.getInstance("SHA-256");
                  byte[] digest = md.digest(cert.getPublicKey().getEncoded());
                  _hpkpCertHashesString = "pin-sha256=\"" + java.util.Base64.getEncoder()
                                          .encodeToString(digest) + "\"; max-age=" + 
                                           _hpkpMaxAge;
              } catch (Exception e) {
                  ;
              }
          }
      }
  }
  </code></pre>
  
  <p>Directives from response header</p>
  
  <pre><code>Public-Key-Pins:pin-sha256="JdZ3itf02UwsCav0X26wcSQLGfo="; max-age=5184000
  Strict-Transport-Security:max-age=5184000
  </code></pre>