簡體   English   中英

Java/Keystore 驗證簽名證書

[英]Java/Keystore Verify Signed certificate

我正在研究嵌入式碼頭服務器和客戶端之間的客戶端證書身份驗證。 他們都使用密鑰庫。 客戶端證書由 CA 簽署的服務器證書簽署。 Jetty 使用 2 方法來驗證客戶端證書 javax.net.ssl.SSLEngine 似乎可以工作,他們也使用上面的代碼。

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){
 ...
}

當然我必須使用第二種方式......所以讓我們專注於這段代碼,這是驗證簽名證書的好方法嗎? 這是我的密鑰庫的轉儲:

客戶端密鑰庫:

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)似乎可以工作。

調試輸出太大,無法放在這里,但這里是堆棧跟蹤:

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,則代碼可以工作,但我不確定我在做什么。

我開始懷疑碼頭代碼,但我不是證書和 SSL 握手方面的專家,所以它也可能來自錯誤的密鑰庫/信任庫。 這就是為什么我沒有在碼頭的板上創建問題並在此之前詢問過,以確保需要更改代碼。

此外,了解如何在 Java 中驗證簽名證書可能很有用。

其實我不需要自己做驗證。

SSLEngine已經在這樣做了。 如果客戶端發送了有效證書,您可以使用getPeerCertificateChain()獲取它:如果客戶端未發送證書或無效證書,則getPeerCertificateChain()將引發異常。

使用 Jetty(或我猜的任何 Java ServletContainer),您只需要檢查 HttpServletRequest 的屬性 ["javax.servlet.request.X509Certificate"] 即可了解客戶端是否發送了有效證書。

我仍然不知道如何在 Java 中驗證證書,但這個解決方案對我來說已經足夠了 :) 我不再需要自己做。 感謝布魯諾!

請檢查您的證書 CRL 或 OCSP 是否可訪問,您可以在證書中找到此類信息,例如

[1]CRL Distribution Point
     Distribution Point Name:
          Full Name:
               URL=http://crl.verisign.com/pca2-g2.crl

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM