使用自签名证书的Java SSL/HTTPS客户端

6

我正在尝试编写一个使用jdk版本1.6.0_32的Java https客户端。我有一个自签名的公共证书,已将其导入到新的信任存储中。问题是我一直收到“Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake”错误信息。SSL调试输出如下:

C:\Users\csheets\eclispe_workspace\sdpweb\InstallSSLCert>java TestCert
keyStore is :
keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
trustStore is: c:\users\csheets\4startrust.ts
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
Subject: CN=4starserver.servehttp.com
Issuer:  CN=4STAR
Algorithm: RSA; Serial number: 0x200000001
Valid from Mon May 14 11:25:15 MDT 2012 until Tue May 14 11:25:15 MDT 2013

trigger seeding of SecureRandom
done seeding SecureRandom
Allow unsafe renegotiation: true
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1320442869 bytes = { 175, 184, 30, 195, 10, 55, 219, 232, 23
, 237, 63, 239, 83, 49, 125, 80, 10, 174, 112, 210, 61, 53, 232, 66, 179, 22, 16
1, 80 }
Session ID:  {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_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, 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_SH
A, 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_WI
TH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
***
main, WRITE: TLSv1 Handshake, length = 75
main, WRITE: SSLv2 client hello message, length = 101
main, READ: SSLv3 Handshake, length = 527
*** ServerHello, SSLv3
RandomCookie:  GMT: 1320442987 bytes = { 158, 143, 79, 29, 193, 160, 122, 201, 8
1, 67, 17, 26, 159, 243, 54, 202, 255, 156, 125, 121, 132, 174, 17, 202, 222, 65
, 252, 77 }
Session ID:  {131, 30, 0, 0, 6, 235, 145, 226, 5, 214, 118, 217, 18, 123, 46, 20
4, 51, 182, 211, 225, 48, 172, 95, 70, 144, 4, 178, 150, 166, 75, 166, 29}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Created:  [Session-1, SSL_RSA_WITH_RC4_128_SHA]
** SSL_RSA_WITH_RC4_128_SHA
*** Certificate chain
chain [0] = [
[
  Version: V3
  Subject: CN=4starserver.servehttp.com
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 129409122589634486230897608496688768265641316152022572826296995250983
  80968933262586507340653723460037384941316405007365056646964455523390263136350462
  59738068084572819329229707448458528878467480278641098016863640927986379246142644
  62745346179244207665720440347282685862962453661441013596685879879277368109494267

public exponent: 65537
Validity: [From: Mon May 14 11:25:15 MDT 2012,
           To: Tue May 14 11:25:15 MDT 2013]
Issuer: CN=4STAR
SerialNumber: [    02000000 01]

]
Algorithm: [SHA1withRSA]
Signature:
0000: 00 8E A1 F4 58 22 F2 C2   A9 1D C6 CB 5A 23 F5 A5  ....X"......Z#..
0010: 02 3A C9 FF 83 96 1A 13   3A 0F 59 D5 1E 1F 56 85  .:......:.Y...V.
0020: AB 4A 46 8D F3 43 E8 BA   B3 F9 B7 8C FB 76 AD D5  .JF..C.......v..
0030: 9F 15 47 DC 30 72 F9 BA   B1 FF DA 2C 25 89 FF 30  ..G.0r.....,%..0
0040: C4 4F BA D6 0C B9 30 10   B0 4B 74 EF 8A F4 5D F1  .O....0..Kt...].
0050: AC 2C 47 D9 C2 F5 A0 AF   CE 8B 76 53 36 A3 BE 11  .,G.......vS6...
0060: 7E BA 1F 4A 67 C1 69 EF   C3 E6 32 E2 0D 09 93 66  ...Jg.i...2....f
0070: 92 21 66 88 95 CA BD C8   FF CF 79 9D 7E F3 DC E0  .!f.......y.....

]
***
Found trusted certificate:
[
[
  Version: V3
  Subject: CN=4starserver.servehttp.com
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 129409122589634486230897608496688768265641316152022572826296995250983
80968933262586507340653723460037384941316405007365056646964455523390263136350462
59738068084572819329229707448458528878467480278641098016863640927986379246142644
62745346179244207665720440347282685862962453661441013596685879879277368109494267

 public exponent: 65537
 Validity: [From: Mon May 14 11:25:15 MDT 2012,
           To: Tue May 14 11:25:15 MDT 2013]
 Issuer: CN=4STAR
 SerialNumber: [    02000000 01]

 ]
Algorithm: [SHA1withRSA]
Signature:
0000: 00 8E A1 F4 58 22 F2 C2   A9 1D C6 CB 5A 23 F5 A5  ....X"......Z#..
0010: 02 3A C9 FF 83 96 1A 13   3A 0F 59 D5 1E 1F 56 85  .:......:.Y...V.
0020: AB 4A 46 8D F3 43 E8 BA   B3 F9 B7 8C FB 76 AD D5  .JF..C.......v..
0030: 9F 15 47 DC 30 72 F9 BA   B1 FF DA 2C 25 89 FF 30  ..G.0r.....,%..0
0040: C4 4F BA D6 0C B9 30 10   B0 4B 74 EF 8A F4 5D F1  .O....0..Kt...].
0050: AC 2C 47 D9 C2 F5 A0 AF   CE 8B 76 53 36 A3 BE 11  .,G.......vS6...
0060: 7E BA 1F 4A 67 C1 69 EF   C3 E6 32 E2 0D 09 93 66  ...Jg.i...2....f
0070: 92 21 66 88 95 CA BD C8   FF CF 79 9D 7E F3 DC E0  .!f.......y.....

]
*** ServerHelloDone
*** ClientKeyExchange, RSA PreMasterSecret, SSLv3
main, WRITE: SSLv3 Handshake, length = 132
SESSION KEYGEN:
PreMaster Secret:
0000: 03 00 07 86 97 89 23 A4   73 85 54 59 A4 76 DD 85  ......#.s.TY.v..
0010: 12 1A 28 1B 71 CC 7A B2   EE 0F 65 60 26 30 6C B4  ..(.q.z...e`&0l.
0020: B4 92 2D 15 50 51 E5 10   77 96 8E B0 4F 30 57 73  ..-.PQ..w...O0Ws
CONNECTION KEYGEN:
Client Nonce:
0000: 4F B4 5C F5 AF B8 1E C3   0A 37 DB E8 17 ED 3F EF  O.\......7....?.
0010: 53 31 7D 50 0A AE 70 D2   3D 35 E8 42 B3 16 A1 50  S1.P..p.=5.B...P
Server Nonce:
0000: 4F B4 5C 6B 9E 8F 4F 1D   C1 A0 7A C9 51 43 11 1A  O.\k..O...z.QC..
0010: 9F F3 36 CA FF 9C 7D 79   84 AE 11 CA DE 41 FC 4D  ..6....y.....A.M
Master Secret:
0000: 60 59 16 75 E0 5E 4B 64   D6 6B 56 18 9B F2 C8 7A  `Y.u.^Kd.kV....z
0010: F8 DF 65 C6 C0 12 92 62   15 A1 4E 5F 53 D3 02 EF  ..e....b..N_S...
0020: 9B EF ED FD 1E 01 61 6F   AC 39 E0 5B AD 87 BF 25  ......ao.9.[...%
Client MAC write Secret:
0000: C1 36 79 97 E6 71 22 D0   27 D0 41 88 F9 F5 8D C2  .6y..q".'.A.....
0010: EA A3 97 FB                                        ....
Server MAC write Secret:
0000: C4 00 15 49 31 29 B2 F3   06 90 59 F0 5A 4D 3D 45  ...I1)....Y.ZM=E
0010: 32 B2 B6 83                                        2...
Client write key:
0000: E6 46 87 A2 16 52 04 11   73 15 E8 23 9F E6 02 A3  .F...R..s..#....
Server write key:
0000: 04 63 1D 64 E7 25 FC E4   53 FC 43 04 33 3C ED 6E  .c.d.%..S.C.3<.n
... no IV used for this cipher
main, WRITE: SSLv3 Change Cipher Spec, length = 1
*** Finished
verify_data:  { 61, 221, 238, 253, 97, 36, 152, 79, 254, 95, 226, 136, 55, 16, 2
07, 66, 58, 197, 233, 254, 125, 99, 11, 0, 138, 51, 139, 62, 175, 123, 52, 167,
131, 216, 245, 97 }
***
main, WRITE: SSLv3 Handshake, length = 60
main, received EOFException: error
main, handling exception: javax.net.ssl.SSLHandshakeException: Remote host close
d connection during handshake
main, SEND SSLv3 ALERT:  fatal, description = handshake_failure
main, WRITE: SSLv3 Alert, length = 22
main, called closeSocket()
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host clos
ed connection during handshake
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)

    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Un
known Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Sou
rce)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Sou
rce)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect
(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown So
urce)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unkn
own Source)
    at TestCert.main(TestCert.java:92)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)
    ... 9 more

我不确定如何解释所有这些信息,但似乎我的证书已被找到并信任 - ClientKeyExchange 是什么意思 - 服务器是否期望客户端身份验证,还是只是交换证书信息。整个Java密钥库、信任库和自签名证书似乎会造成很多复杂性和混淆 - 至少对我来说是这样。

我的测试客户端代码如下:

import java.io.*;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.*;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import java.security.*;

public class TestCert {
public static void main(String[] args) throws Exception {
    System.setProperty("javax.net.debug", "ssl");
    System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
    System.setProperty("javax.net.ssl.trustStore", "c:\\users\\csheets\\4startrust.ts");
    System.setProperty("javax.net.ssl.trustStorePassword", "mypassword");


    SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();

    URL url = new URL("https://4starserver.servehttp.com:777/?username=0&password=0&command=WEBAUTH&TRAN=2&MERCHANT=9999999999119911&FNAME=TONY&LNAME=PISCOPO&CC=4111111111111111&EXP=0613&AMOUNT=99.98");
    HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
    conn.setSSLSocketFactory(sslsocketfactory);

    InputStream inputstream = conn.getInputStream();
    InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
    BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

    String string = null;
    while ((string = bufferedreader.readLine()) != null) {
        System.out.println("Received " + string);
    }
}
}

我尝试了其他方法,例如创建自己的TrustManager和TrustManager,但似乎也没有起作用。非常感谢您的任何帮助。
更新: 服务器端口已更改为443,因此可以使用{{link1:Qualys SSL Lab test}}进行测试,我得到了以下结果:
Common Error Messages

Connect timed out - server did not respond to our connection request
No route to host - unable to reach the server
Unable to connect to server - failed to connect to the server
Unrecognized SSL message, plaintext connection? - the server responded with plain-text HTTP on HTTPS port
Received fatal alert: handshake_failure - this is either a faulty SSL server or some other server listening on port 443; if the SSL version of the web site works in your browser, please report this issue to us
Known Issues

Could not generate DH keypair - due to a known problem with the underlying SSL library (Sun's JSSE implementation) we are unable to assess the sites that offer only DHE handshakes stronger than 1024 bits.

奇怪的是,如果我只是在浏览器中输入URLhttps://server.com/,似乎就能从服务器得到响应 - 但在服务器上显然会有多个请求/连接。看起来服务器端似乎有些不对劲?
3个回答

4
您的证书已受信任(使用您的自定义信任存储库),这不是信任管理器问题。您无需允许不安全的重协商(也无需指定默认的SSLSocketFactory)。
TLS设置似乎存在问题,因为它可以使用System.setProperty("https.protocols", "SSLv3")运行。如果使用openssl s_client强制使用-tls1,还会出现握手问题。
如果您控制服务器,建议将其放在443端口上,并通过Qualys SSL labs测试进行测试(此测试比许多其他测试更详细并捕获更多问题)。

将https.protocols属性设置为“SSLv3”即可解决问题!我想更深入地了解一下 - 这实际上是做什么的,与执行以下操作有何不同:SSLContext sslContext = SSLContext.getInstance(“SSLv3”); 我只需设置系统属性就可以了,除非出于某种原因存在问题。此外,感谢您提醒Qualys SSL实验室测试 - 我之前并不知道。 - csheets
1
SSLContext.getInstance(...) 返回一个实现至少请求的安全套接字协议的实例。返回的实例也可以实现其他协议。相比之下,https.protocolsHttpsURLConnection 使用的套接字上显式设置启用的协议:这是用于指定使用 SSLv3/TLSv1.x 的内容。 - Bruno
我通常建议尽可能升级SSLv3、TLSv1.0、TLSv1.1等版本。理想情况下,现在应该淘汰SSLv3,并至少使用TLS 1.1(以解决BEAST漏洞等问题)。现在很少有服务器不支持TLS 1.0(你正在尝试使用的服务器之一)。 - Bruno
我已更新问题,并附上了Qualys SSL测试的结果——似乎服务器端有些不太对劲?无论如何,我现在认为通过https.protocols系统属性明确地设置SSLv3套接字是可以满足我的需求的。感谢大家的帮助。 - csheets
我有类似的问题,请看一下这个链接:http://stackoverflow.com/questions/12822436/weblogic-webservices-communication-over-ssl - Balconsky

1

针对有类似问题的人:我也曾遇到Java和SSL使用时的问题,其中服务器使用了自签名证书。我尝试使用如下代码: System.setProperty("https.protocols", "SSLv3"); 正如一个答案中所提到的。但是这并没有对我起作用。不过,类似以下代码确实有效: System.setProperty("https.protocols", "TLSv1");


-3

尝试在您的主类中实现X509TrustManager类,然后执行以下操作:

    private static void trustAllHttpsCertificates() throws Exception {
       //  Create a trust manager that does not validate certificate chains:
       javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
       javax.net.ssl.TrustManager tm = new YourMainClass();
       trustAllCerts[0] = tm; 
       javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
       sc.init(null, trustAllCerts, null);
       javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

并覆盖此内容,

    @Override
    public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
       return;
    }

    @Override
    public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
       return;
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
       return null;
    }

我希望能帮到你。:)


不要禁用证书验证,这会打开中间人攻击的大门。此外,该问题提供了一个特定的信任存储库(这是正确的方法),并且证书是可见信任的。 - Bruno
我实际上尝试了这种方法进行测试,只是想看看是否能让某些东西/任何东西工作 - 对于我来说没有任何效果,不知道为什么 - 仍然遇到相同的错误。将系统属性“https.protocols”设置为“SSLv3”似乎可以起作用 - 不确定原因,但现在就这么做 :-) 感谢您的帮助。 - csheets
嗨@csheets,对我来说TestCert类返回Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake。我认为这是服务器的问题。我正在使用实现X509TrustManager进行测试。你需要返回或接收一些东西吗?例如XML或文件? - hekomobile
同意 - 我认为这也是服务器问题 - 根据其他测试,似乎有些不对劲 - 请参见问题的更新以获取Qualys SSL测试的测试结果。但我现在认为我已经得到了答案 - 将https.protocols系统属性显式设置为SSLv3 - 在客户端或服务器上没有错误,似乎可以正常工作。 - csheets

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接