Java/密钥库验证签名证书 [英] Java/Keystore Verify Signed certificate

查看:167
本文介绍了Java/密钥库验证签名证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究嵌入式码头服务器和客户端之间的客户端证书身份验证.他们都使用密钥库.客户端证书由CA签署的服务器证书签署. Jetty使用2种方法来验证客户端证书javax.net.ssl.SSLEngine似乎有效,并且它们也使用上面的代码.

I'm working on a client-cert authentication between a embedded jetty server and a client. They both use keystore. The client certificate is signed by the server's certificate which is signed by a CA. Jetty use 2 method to authenticate a client certificate, javax.net.ssl.SSLEngine which seems to work and they also use the code above.

List<X509Certificate> certList = Certificate chain sent by the client
KeyStore truststore = server's truststore

//No use of CRL/OSCP/CRLDP
_crls = null;
_enableOCSP = false;
_enableCRLDP = false;

try{
 X509CertSelector certSelect = new X509CertSelector();
 certSelect.setCertificate((X509Certificate) certList.get(0));

 // Configure certification path builder parameters
 PKIXBuilderParameters pbParams = new PKIXBuilderParameters(truststore, certSelect);
 pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList)));

 // Set maximum certification path length
 pbParams.setMaxPathLength(-1);

 // Enable revocation checking
 pbParams.setRevocationEnabled(true);

 // Set static Certificate Revocation List
 if (_crls != null && !_crls.isEmpty())
     pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(_crls)));

  // Enable On-Line Certificate Status Protocol (OCSP) support
  if (_enableOCSP)
      Security.setProperty("ocsp.enable","true");

  // Enable Certificate Revocation List Distribution Points (CRLDP) support
  if (_enableCRLDP)
      System.setProperty("com.sun.security.enableCRLDP","true");

 // Build certification path
 CertPathBuilderResult buildResult = CertPathBuilder.getInstance("PKIX").build(pbParams);               

 // Validate certification path
 CertPathValidator.getInstance("PKIX").validate(buildResult.getCertPath(),pbParams);
}catch(GeneralSecurityException gse){
 ...
}

我当然必须使用第二种方式... 因此,让我们专注于此代码,这是验证签名证书的好方法吗? 这是我的密钥库的转储:

Of course I must use this second way... So let's concentrate on this code, is this a good way to verify a signed certificate ? Here is a dump of my keystores :

客户端密钥库:

Entry type: PrivateKeyEntry 
Certificate chain length: 2
Certificate[1]: 
Owner: EMAILADDRESS=truc@ok.com, CN=Servlet, OU=dev, O=Imbasoft, ST=Ile-de-France, C=FR 
Issuer: EMAILADDRESS=contact@greenpacs.com, CN=Greenpacs, OU=dev, O=Imbasoft, L=Bondy, ST=Ile-de-France, C=FR 
...

Certificate[2]: 
Owner: EMAILADDRESS=contact@greenpacs.com, CN=Greenpacs, OU=dev, O=Imbasoft, L=Bondy, ST=Ile-de-France, C=FR
Issuer: EMAILADDRESS=ghetolay@imbasoft.com, CN=Greenpacs Certificate Authority, OU=dev, O=Imbasoft, ST=Ile-de-France, C=FR 
...

服务器信任库:

Entry type: trustedCertEntry

Owner: EMAILADDRESS=contact@greenpacs.com, CN=Greenpacs, OU=dev, O=Imbasoft, L=Bondy, ST=Ile-de-France, C=FR
Issuer: EMAILADDRESS=ghetolay@imbasoft.com, CN=Greenpacs Certificate Authority, OU=dev, O=Imbasoft, ST=Ile-de-France, C=FR

我不确定这些密钥库,但尝试使用其他密钥库(将CA证书添加到客户端的证书链,将证书添加到信任库),但验证仍然失败.有了这些密钥库,第一种验证方法(SSLEngine)似乎可以正常工作.

I'm not sure about these keystores but I tried with different one (adding the CA certificate to the client's certificate chain, adding certificate to the truststore) and the validation still fail. And with these keystores the first way of validation (SSLEngine) seems to work.

调试输出太大,无法将其放在此处,但这是stacktrace:

The debug output is too big to put it here but here is the stacktrace :

java.security.cert.CertPathValidatorException: Could not determine revocation status
    at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:153)
    at sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:325)
    at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:187)
    at java.security.cert.CertPathValidator.validate(CertPathValidator.java:267)
    at MainClass.main(MainClass.java:75)
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:197)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:255)
    at sun.security.provider.certpath.CrlRevocationChecker.buildToNewKey(CrlRevocationChecker.java:583)
    at sun.security.provider.certpath.CrlRevocationChecker.verifyWithSeparateSigningKey(CrlRevocationChecker.java:459)
    at sun.security.provider.certpath.CrlRevocationChecker.verifyRevocationStatus(CrlRevocationChecker.java:339)
    at sun.security.provider.certpath.CrlRevocationChecker.verifyRevocationStatus(CrlRevocationChecker.java:248)
    at sun.security.provider.certpath.CrlRevocationChecker.check(CrlRevocationChecker.java:189)
    at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:131)
    ... 4 more

如果我禁用吊销,或者如果我将最后一个证书(而不是第一个证书)设置为X509CertSelector,则代码可以正常工作,但是我不确定自己在做什么.

If I disable the revocation or if I set the last certificate (instead of the first) as X509CertSelector the code work but I'm not sure of what I'm doing.

我开始怀疑码头代码,但我不是证书和SSL握手方面的专家,因此它也可能来自错误的密钥库/信任库.这就是为什么我没有在码头的董事会上创建问题,而是在这里问过这个问题,以确保需要更改代码的原因.

I'm starting to doubt about the jetty code but I'm not an expert in certificate and SSL handshaking so it could also come from bad keystore/truststore. That's why I did not create a issue on jetty's board and asked here before, to be sure the code needs to be changed.

另外,了解如何在Java中验证签名证书可能很有用.

Also It could be useful to know how to validate a signed certificate in Java.

推荐答案

实际上,我不需要自己进行验证.

Actually I don't need to do the validation myself.

SSLEngine已经在执行此操作,如果客户端发送了有效的证书,则可以使用getPeerCertificateChain()获取它,如果客户端没有发送证书或无效的证书,则getPeerCertificateChain()返回null 引发异常.

The SSLEngine is already doing it and if a valid certificate is sent by the client you can get it using getPeerCertificateChain(), if no certificate or an invalid certificate is sent by the client getPeerCertificateChain() return null throws a exception.

使用码头(或我猜想的任何Java ServletContainer),您只需要检查HttpServletRequest的attribute ["javax.servlet.request.X509Certificate"]即可知道客户端是否发送了有效证书.

Using jetty (or any Java ServletContainer I guess) you just need to check the HttpServletRequest's attribute["javax.servlet.request.X509Certificate"] to know if a valid certificate was sent by the client.

我仍然不知道如何在Java中验证证书,但是这种解决方案对我来说已经足够了:)我不再需要自己做.多亏布鲁诺!

I still don't know how to validate a certificate in Java but this solution is enough for me :) I don't need to do it myself anymore. Thanks to Bruno !

这篇关于Java/密钥库验证签名证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆