0

我正在尝试使用 Apache HTTPClient 实现客户端和服务器身份验证,并使用自签名证书对其进行测试。我试图在这里遵循几个教程和类似问题的答案,但没有成功。我试图尽可能详细地说明我一直在做的所有步骤,希望有人能指出我做错了什么:

  1. req.conf为配置创建了一个文件

    [req]
    prompt=no
    distinguished_name = req_distinguished_name
    
    [ req_distinguished_name ]
    O=selfSignedO
    CN=selfSignedCn
    DC=selfSignedDc
    
  2. 生成的服务器私钥和自签名证书

    openssl req \
     -config req.conf \
     -x509 \
     -newkey rsa:4096 \
     -keyout server/server-private-key.pem \
     -out server/server.crt \
     -days 3650 \
     -nodes 
    
  3. 创建了包含上一步中创建的私钥和证书的 PKCS12 密钥库

     openssl pkcs12 \
     -export \
     -out server/server-key-store.p12 \
     -inkey server/server-private-key.pem \
     -in server/server.crt
    

    假设我使用的密码是123456

  4. 生成客户端私钥和证书签名请求

    openssl req \
     -config req.conf \
     -new \
     -newkey rsa:4096 \
     -out client/client-request.csr \
     -keyout client/client-private-key.pem \
     -nodes
    
  5. 使用服务器的私钥和证书对客户端的证书签名请求进行签名

    openssl x509 \
     -req \
     -days 360 \
     -in client/client-request.csr \
     -CA server/server.crt \
     -CAkey server/server-private-key.pem \
     -CAcreateserial \
     -out client/client-signed-cert.crt \
     -sha256
    
  6. 创建了一个 PKCS12 密钥库,其中包含上一步中创建的客户端私钥和证书证书。

     openssl pkcs12 \
      -export \
      -out client/client-keystore.p12 \
      -inkey client/client-private-key.pem \
      -in client/client-signed-cert.crt \
      -certfile server/server.crt
    

    我们123456再次用作密码。

  7. 生成的包含客户端签名证书的服务器信任库

    keytool \
     -import \
     -trustcacerts \
     -alias root \
     -file client/client-signed-cert.crt \
     -keystore server/server-trust-store.jks
    

    密码?123456

  8. 卷曲正在工作,但仅限于-k

    curl -k \
       --cert client/client-signed-cert.crt \
       --key client/client-private-key.pem \
       https://localhost:443:/my/endpoint
    

    没有-k我得到错误:

    curl: (60) SSL certificate problem: self signed certificate
    More details here: https://curl.haxx.se/docs/sslcerts.html
    
    curl performs SSL certificate verification by default, using a "bundle"
     of Certificate Authority (CA) public keys (CA certs). If the default
     bundle file isn't adequate, you can specify an alternate file
     using the --cacert option.
    If this HTTPS server uses a certificate signed by a CA represented in
     the bundle, the certificate verification probably failed due to a
     problem with the certificate (it might be expired, or the name might
     not match the domain name in the URL).
    If you'd like to turn off curl's verification of the certificate, use
     the -k (or --insecure) option.
    HTTPS-proxy has similar options --proxy-cacert and --proxy-insecure.
    
  9. 已配置的 Apache HTTPClient:

    private HttpClient createClient() throws Exception {
        String keyPassword = "123456";
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(resourceAsStream("/client/client-key-store.p12"), keyPassword.toCharArray());
        SSLContext sslContext = new SSLContextBuilder()
            .setProtocol("TLSv1.2")
            .loadKeyMaterial(ks, keyPassword.toCharArray())
            .loadTrustMaterial(null, new TrustSelfSignedStrategy())
            .build()
        return HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(new NoopHostnameVerifier())
                .build();
    }
    

    (构造是通过多种方法完成的,我在这里挤成一个,所以如果有什么奇怪或丢失的东西,请告诉我,也许我错误地粘贴了一些东西。)

但是当尝试发送与 Curl 相同的请求时,我得到:

Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2038)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1135)
    at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1779)
    at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:124)
    at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:1156)
    at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1266)
    at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1178)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:348)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:987)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:373)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:394)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
4

0 回答 0