Chúng tôi đang sử dụng máy khách java (openJDK 1.8.0) để gọi api yêu cầu xác thực lẫn nhau. Để thực hiện việc này, chúng tôi sử dụng các tệp JKS tiêu chuẩn Java làm kho khóa và kho tin cậy (cùng một tệp chứa chứng chỉ tin cậy và chứng chỉ nhận dạng/khóa riêng). Java mẫu mà chúng tôi sử dụng để kiểm tra như sau::
KeyStore clientKeyStore = KeyStore.getInstance("JKS");
clientKeyStore.load(FileInputStream mới("./client.keystore"),
mật khẩu.toCharArray());
// tạo trình quản lý kết nối máy khách để sử dụng trong việc tạo httpclients
PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
SSLContext sslContext = SSLContextBuilder.create()
.loadKeyMaterial(clientKeyStore, mật khẩu.toCharArray())
.loadTrustMaterial(clientKeyStore, null).build();
// tạo ứng dụng khách dựa trên trình quản lý và sử dụng nó để thực hiện cuộc gọi
CloseableHttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(mgr)
.setSslcontext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier() mới)
.xây dựng();
HttpPost httppost = HttpPost mới("https://someUrl");
Thông số chuỗi = "";
Thông số StringEntity = StringEntity mới(params);
httppost.setEntity(param);
System.out.println("Đang gửi yêu cầu.............");
Phản hồi httpResponse = httpClient.execute(httppost);
Trong quá trình bắt tay SSL là bước cuối cùng của "serverhello", máy chủ yêu cầu danh tính của khách hàng bằng cách đưa ra "yêu cầu chứng chỉ" - vui lòng tìm yêu cầu bên dưới::
***Yêu cầu chứng chỉ
Các loại chứng chỉ: RSA, ECDSA, DSS
Thuật toán chữ ký được hỗ trợ: SHA512withRSA, Không xác định (băm:0x6, chữ ký:0x2), SHA512withECDSA, SHA384withRSA, Không xác định (băm:0x5, chữ ký:0x2), SHA384withECDSA, SHA256withRSA, SHA256withDSA, SHA256withECDSA, SHA224withRSA, SHA224withDSA, SHA224withECDSA, SHA1withRSA, SHA1withDSA, SHA1withECDSA
Cơ quan cấp chứng chỉ:
Sau đó, chúng ta thấy dòng sau cho biết keyManager của java không thể tìm thấy bất kỳ thứ gì được ký bởi cùng một người ký.
*** Máy chủXin chàoXong
[đọc] băm MD5 và SHA1: len = 4
0000: 0E 00 00 00 ....
Cảnh báo: không tìm thấy chứng chỉ phù hợp - tiếp tục mà không cần xác thực ứng dụng khách
***Chuỗi chứng chỉ
***
|
Chúng tôi đã xác minh rằng chứng chỉ tồn tại trong kho khóa và đó là chứng chỉ hợp lệ (bằng cách mở nó trong hộp Windows, hộp này sẽ không mở nếu có chứng chỉ không hợp lệ). Vì vậy, kho khóa của chúng tôi có một chuỗi: myIdentity >> được ký bởi CA trung gian >> được ký bởi CA gốc
Một số điều chúng tôi đã thử (không gặp may mắn) là:
- Hãy thử ghi đè keystoremanager để trả về bí danh được mã hóa cứng, bí danh của chứng chỉ trong keystore.jks
- 尝试将身份证书和 CA 证书拆分到两个单独的文件中,即单独的 keystore.jks 和 truststore.jks
值得分享的是,如果我们使用 cURL,同样的连接也能正常工作。在 cURL 的情况下,我们必须显式传递客户端证书作为参数(cURL 没有 keystore 的概念)并且我们使用的是 linux 默认 keystore (/etc/pki/tls/certs/ca-bundle.crt)
curl -vvv GET https://api.someone.com/some/path -E /home/certificates/client.test.pem --key /home/certificates/client.test.key
我不确定还有哪些其他细节可以增加值(value),但我很乐意分享所有可能需要的细节(除了我的私钥:-P)
我遇到了和你描述的一样的问题。我遇到的问题是我使用 Java 加载了 keystore :
System.setProperty("javax.net.ssl.keyStore", "/path/key.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "pass");
当服务器请求 ClientCertificate 时,所有得到的是:
*** CertificateRequest Cert Types: RSA, DSS Supported Signature Algorithms: SHA512withRSA, SHA512withECDSA, SHA384withRSA, SHA384withECDSA, SHA256withRSA, SHA256withECDSA, Unknown (hash:0x4,signature:0x2), SHA224withRSA, SHA224withECDSA, Unknown (hash:0x3,signature:0x2), SHA1withRSA, SHA1withECDSA, SHA1withDSA Cert Authorities: *** ServerHelloDone Warning: no suitable certificate found - continuing without client authentication
The solution for this was to load the keystore in a different way as described by:Java SSLHandshakeException "no cipher suites in common"
Basically what I did was to change how I created the SSLContext:
From:
System.setProperty("javax.net.ssl.keyStore", "/path/key.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "pass");
System.setProperty("javax.net.ssl.trustStore", "/path/trust.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
SSLContext c = SSLContext.getInstance("TLSv1.2");
c.init(null, null, null);
收件人:
// instantiate a KeyStore with type JKS
KeyStore ks = KeyStore.getInstance("JKS");
// load the contents of the KeyStore
final char[] keyPasswd = "pass".toCharArray();
ks.load(new FileInputStream("/path/key.jks"), keyPasswd);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(ks, keyPasswd);
SSLContext c = SSLContext.getInstance("TLSv1.2");
c.init(keyManagerFactory.getKeyManagers(), null, null);
然后结果是:
*** CertificateRequestCert Types: RSA, DSSSupported Signature Algorithms: SHA512withRSA, SHA512withECDSA, SHA384withRSA, SHA384withECDSA, SHA256withRSA, SHA256withECDSA, Unknown (hash:0x4, signature:0x2), SHA224withRSA, SHA224withECDSA, Unknown (hash:0x3, signature:0x2), SHA1withRSA, SHA1withECDSA, SHA1withDSACert Authorities:*** ServerHelloDonematching alias: ibmwebspheremq01
Tôi là một lập trình viên xuất sắc, rất giỏi!