Tôi đang làm việc trên xác thực ứng dụng khách-cert giữa máy chủ cầu nối được nhúng và máy khách. Cả hai đều sử dụng kho khóa. Chứng chỉ ứng dụng khách được ký bởi chứng chỉ của máy chủ được ký bởi một CA. Jetty sử dụng 2 phương pháp để xác thực chứng chỉ ứng dụng khách, javax.net.ssl.SSLEngine có vẻ hoạt động và họ cũng sử dụng mã ở trên.Java/Keystore Xác minh chứng chỉ đã ký
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){
...
}
Tất nhiên tôi phải sử dụng cách thứ hai này ... Vì vậy, hãy tập trung vào mã này, đây là một cách tốt để xác minh giấy chứng nhận có chữ ký? Đây là một bãi chứa của keystores tôi:
Khách hàng Keystore:
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: [email protected], CN=Servlet, OU=dev, O=Imbasoft, ST=Ile-de-France, C=FR
Issuer: [email protected], CN=Greenpacs, OU=dev, O=Imbasoft, L=Bondy, ST=Ile-de-France, C=FR
...
Certificate[2]:
Owner: [email protected], CN=Greenpacs, OU=dev, O=Imbasoft, L=Bondy, ST=Ile-de-France, C=FR
Issuer: [email protected], CN=Greenpacs Certificate Authority, OU=dev, O=Imbasoft, ST=Ile-de-France, C=FR
...
server truststore:
Entry type: trustedCertEntry
Owner: [email protected], CN=Greenpacs, OU=dev, O=Imbasoft, L=Bondy, ST=Ile-de-France, C=FR
Issuer: [email protected], CN=Greenpacs Certificate Authority, OU=dev, O=Imbasoft, ST=Ile-de-France, C=FR
Tôi không chắc chắn về những keystores nhưng tôi đã cố gắng với một khác nhau (thêm Chứng nhận CA cho chuỗi chứng chỉ của khách hàng, thêm chứng chỉ vào truststore) và xác thực vẫn không thành công. Và với những keystores này, cách xác thực đầu tiên (SSLEngine) dường như hoạt động.
Sản lượng debug là quá lớn để đặt nó ở đây nhưng đây là 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
Nếu tôi vô hiệu hóa việc thu hồi hoặc nếu tôi đặt giấy chứng nhận cuối cùng (thay vì là người đầu tiên) như X509CertSelector công việc mã nhưng tôi không chắc chắn về những gì tôi đang làm.
Tôi bắt đầu nghi ngờ về mã cầu nối nhưng tôi không phải là chuyên gia về chứng chỉ và bắt tay SSL vì vậy nó cũng có thể đến từ kho khóa/kho tin xấu. Đó là lý do tại sao tôi đã không tạo ra một vấn đề trên tàu của cầu tàu và hỏi ở đây trước, để chắc chắn rằng mã cần phải được thay đổi.
Cũng có thể hữu ích khi biết cách xác thực chứng chỉ đã ký bằng Java.
Tại sao bạn không để người quản lý tin cậy qua JSSE thực hiện tất cả điều này cho bạn? – Bruno
Bởi vì máy chủ của tôi cũng chấp nhận kết nối không xác thực. Tôi phải để cho nó chấp nhận tất cả các kết nối đầu tiên và sau đó trong một số trường hợp xác nhận chứng chỉ của khách hàng nếu có. – Ghetolay
Không, bạn chỉ cần tạo chứng chỉ ứng dụng khách bằng tùy chọn wantClientAuth (thay vì cần). – Bruno