代码之家  ›  专栏  ›  技术社区  ›  Gui13

Java-使用客户端证书身份验证时取消Ssl流

  •  3
  • Gui13  · 技术社区  · 6 年前

    我想不出这个。

    我有一个单元测试,它使用客户端证书身份验证来执行到我的服务的连接。

    // generate a valid client cert and store it in a keystore
    String keystorePassword = "xxx";
    InputStream pkcs12 = UnitTests.generatePkcs12ForUser(user, keystorePassword, 3600);
    KeyStore ks = KeyStore.getInstance("pkcs12");
    ks.load(pkcs12, keystorePassword.toCharArray());
    
    
    String url = getBaseServerUrl();
    
    // prepare a ssl context that has the keystore with client cert and key
    SSLContext sslContext = SSLContexts.custom()
                                       .loadKeyMaterial(ks, keystorePassword.toCharArray())
                                       // trust all SSL certs
                                       .loadTrustMaterial((X509Certificate[] chain, String authType) -> true)
                                       .build();
    
    // validate any hostname, and don't follow 3XX responses
    HttpClient httpClient = HttpClients.custom()
                                       .setSSLContext(sslContext)
                                       .setSSLHostnameVerifier((a,b) -> true)
                                       .disableRedirectHandling()
                                       .build();
    
    // this fails catastrophically
    HttpResponse response = httpClient.execute(new HttpGet(url));
    

    我使用的是Java 8,我的服务器位于使用Nginx的反向代理之后。

    我的单元测试失败,出现如下异常:

    javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1002)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
    [...]
    Caused by: java.io.EOFException: SSL peer shut down incorrectly
        at sun.security.ssl.InputRecord.read(InputRecord.java:505)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
        ... 43 more
    

    我可以在Nginx错误中看到。记录以下行:

    2018/05/18 15:34:12 [crit] 42#42: *327 SSL_do_handshake() failed (SSL: error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error) while SSL handshaking, client: 172.18.0.1, server: 0.0.0.0:443
    

    我已经在互联网上搜索这个错误的原因,我觉得我已经用尽了一切手段。

    我尝试过的事情的非详尽列表:

    • 强制java使用TlsV1。1个带 -Dhttps.protocols=Tlsv1.1 -&燃气轮机;仍然失败
    • 试图为 loadTrustMaterial 始终使用自己的密钥->仍然失败
    • 使用具有相同Ssl/密钥库参数集的Jersey客户端->仍然失败
    • 尝试了1.8的所有JDK版本:OpenJDK、Oracle和Oracle with Crypto Extensions(JCE)
    • 搜索nginx错误似乎意味着传递的证书不正确,因此我。。。
    • 。。。在调试器和 curl ed相同地址->行得通?!
    • 有线共享连接并检查TLS协商。将其与工作样本(简单 curl -k <url> 以上内容完美无瑕):
      • 看到了一些关于 ALPN 但在Java中启用它并不能修复异常。
      • 看到了不同的加密算法发布,但没有什么突出的

    你们有什么想法吗?我开始发疯了。我有一种预感,我没有正确设置连接,但我看不到在哪里。

    1 回复  |  直到 3 年前
        1
  •  0
  •   Gui13    5 年前

    对于那些没有阅读评论的人:我找到了答案:我使用subjectAltName作为存储,而不是一个替代名称。

    Java似乎对此不满意,并拒绝连接。