0

我在尝试连接到 https 站点时遇到异常。我的代码是用 Java 编写的。它适用于我的笔记本电脑,但不适用于我的 Linux 服务器,我不知道如何调试它。

我已检索 SSL 证书并导入到 cacerts 信任库。

Java代码如下

        System.setProperty("javax.net.debug", "ssl");

        String cacerts_file = System.getProperty("java.home")
                + "/lib/security/cacerts".replace('/', File.separatorChar);

        System.out.println(System.getProperty("javax.net.ssl.trustStore"));
        System.out.println("cacerts_file: " + cacerts_file);

        System.out.println(System.getProperty("javax.net.ssl.trustStore"));

        KeyStore ks = KeyStore.getInstance("JKS");
        FileInputStream in2 = new FileInputStream(cacerts_file);
        ks.load(in2, "changeit".toCharArray());

        System.out.println(ks.containsAlias("badoojira"));
        Enumeration<String> lAliases = ks.aliases();
        while (lAliases.hasMoreElements()) {
            String lAlias = (String) lAliases.nextElement();
            System.out.println(lAlias);
        }

        javax.net.ssl.KeyManagerFactory lKeyManagerFactory = javax.net.ssl.KeyManagerFactory
                .getInstance("SunX509");
        lKeyManagerFactory.init(ks, "changeit".toCharArray());
        javax.net.ssl.SSLContext lSSLContext = javax.net.ssl.SSLContext.getInstance("TLS");
        lSSLContext.init(lKeyManagerFactory.getKeyManagers(), null, null);
        SSLSocketFactory lSSLSocketFactory = lSSLContext.getSocketFactory();
        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(lSSLSocketFactory);
        SSLSocket socket = (SSLSocket) lSSLSocketFactory
                .createSocket("wiki.badoojira.com", 443); 
        String[] suites = socket.getSupportedCipherSuites();
        socket.setEnabledCipherSuites(suites);

        // start handshake
        socket.startHandshake();

我已经在服务器中使用 keystore 命令验证 System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar) 指向的 cacerts 通过调用具有实际证书一个“密钥库列表”。

例外是:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
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:1718)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:962)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1143)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1170)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1154)
at com.corp.GetStatusPage.oneMoreTest(GetStatusPage.java:105)
at com.corp.GetStatusPage.main(GetStatusPage.java:35)

带有调试跟踪(已编辑)

    cacerts_file: /usr/lib64/jvm/java-1.7.0-sun-1.7.0/jre/lib/security/cacerts
    default truststore: /usr/lib64/jvm/java-1.7.0-sun-1.7.0/jre/lib/security/cacerts
    null
    true

    digicertassuredidrootca
    trustcenterclass2caii
    thawtepremiumserverca
    certifjira.com <<-- My certificate

    [Edited - removed all other default certificates aliases]

    trustStore is: /usr/lib64/jvm/java-1.7.0-sun-1.7.0/jre/lib/security/cacerts
    trustStore type is : jks
    trustStore provider is :
    init truststore
    adding as trusted cert:
      Subject: CN=SwissSign Platinum CA - G2, O=SwissSign AG, C=CH
      Issuer:  CN=SwissSign Platinum CA - G2, O=SwissSign AG, C=CH
      Algorithm: RSA; Serial number: 0x4eb200670c035d4f
      Valid from Wed Oct 25 08:36:00 UTC 2006 until Sat Oct 25 08:36:00 UTC 2036

    adding as trusted cert:
      Subject: EMAILADDRESS=personal-freemail@thawte.com, CN=Thawte Personal Freemail CA, OU=Certification Services Division, O=Thawte Consulting, L=Cape Town, ST=Western Cape, C=ZA
      Issuer:  EMAILADDRESS=personal-freemail@thawte.com, CN=Thawte Personal Freemail CA, OU=Certification Services Division, O=Thawte Consulting, L=Cape Town, ST=Western Cape, C=ZA
      Algorithm: RSA; Serial number: 0x123df0e7da2a2247a43889e08aeec967
      Valid from Mon Jan 01 00:00:00 UTC 1996 until Fri Jan 01 23:59:59 UTC 2021

    adding as trusted cert:
      Subject: EMAILADDRESS=server-certs@thawte.com, CN=Thawte Server CA, OU=Certification Services Division, O=Thawte Consulting cc, L=Cape Town, ST=Western Cape, C=ZA
      Issuer:  EMAILADDRESS=server-certs@thawte.com, CN=Thawte Server CA, OU=Certification Services Division, O=Thawte Consulting cc, L=Cape Town, ST=Western Cape, C=ZA
      Algorithm: RSA; Serial number: 0x34a4fff630af4ca53c331742a1946675
      Valid from Thu Aug 01 00:00:00 UTC 1996 until Fri Jan 01 23:59:59 UTC 2021

    adding as trusted cert:
      Subject: CN=*.certifjira.com, O=Trading Limited, L=London, ST=United Kingdom, C=GB
      Issuer:  CN=VeriSign Class 3 Secure Server CA - G3, OU=Terms of use at https://www.verisign.com/rpa (c)10, OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
      Algorithm: RSA; Serial number: 0x62a8e5628239c977eab16142cf0e8e0f
      Valid from Tue May 27 00:00:00 UTC 2014 until Thu May 28 23:59:59 UTC 2015

    [Edited to remove default certificates]

    trigger seeding of SecureRandom
    done seeding SecureRandom
    %% No cached client session
    *** ClientHello, TLSv1
    RandomCookie:  GMT: 1415190323 bytes = { 8, 10, 86, 52, 89, 227, 192, 166, 138, 175, 232, 157, 182, 160, 237, 133, 188, 63, 103, 151, 97, 195, 110, 180, 183, 28, 103, 245 }
    Session ID:  {}
    Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA, TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_DH_anon_WITH_RC4_128_MD5, TLS_DH_anon_WITH_AES_128_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, TLS_ECDH_anon_WITH_RC4_128_SHA, TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_ECDH_anon_WITH_NULL_SHA, TLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_RC4_40_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5]
    Compression Methods:  { 0 }
    Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
    Extension ec_point_formats, formats: [uncompressed]
    ***
    main, WRITE: TLSv1 Handshake, length = 213
    main, WRITE: SSLv2 client hello message, length = 227
    main, READ: TLSv1 Alert, length = 2
    main, RECV TLSv1 ALERT:  fatal, handshake_failure
    main, called closeSocket()
    main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

非常感谢您的帮助。

4

2 回答 2

0
  1. 您的javax.net.ssl.trustStore设置仅实现了默认设置。删除它们。

  2. 密钥库不是信任库。除非您通过添加自己的私钥和证书来破坏 Java 信任库,否则您指定的密钥库应该与信任库不同。

  3. 除非您要连接的服务器需要客户端证书,否则您根本不需要密钥库。所以修复或删除它。

  4. 您需要将确切的异常和堆栈跟踪粘贴到您的问题中,以获得进一步的帮助。

于 2014-11-05T00:16:54.900 回答
0

感谢这里的一些问题,我可以通过在我的代码中添加以下内容来发现我的 2 个环境中启用的协议有所不同:

     String[] lEnabledProtocols = socket.getEnabledProtocols();
     for (int i = 0; i < lEnabledProtocols.length; i++) {
         String lProtocol = lEnabledProtocols[i];
         System.out.println("\t" + lProtocol);
     }

这表明在工作环境中我只获得了 SSLv3、TLSv1,而在握手失败的环境中我获得了 SSLv2Hello、SSLv3、TLSv1。所以我尝试专门设置启用的协议。

        String[] lMyProtocols = { "SSLv3", "TLSv1" };
        socket.setEnabledProtocols(lMyProtocols);

事实证明这对我有用。希望明确设置这些协议没有缺点。

于 2014-11-07T11:37:16.023 回答