从文件导入证书时SSL握手失败

我正在创建一个HTTPS服务器并自己validation证书。

我有一个奇怪的错误。

当我生成证书并添加该密钥库时,我能够进行SSL握手。

keytool -genkey -keyalg rsa -alias mycert -keystore lig.keystore -storepass changeit -keypass changeit

当我使用keytool导入证书并将其添加到密钥库时,我收到SSH Handshake Failure错误。

keytool -noprompt -importcert -file certDer -alias mycert -keystore lig.keystore -storepass changeit -keypass changeit

确切地说,第一个是自签名证书。 第二个是第三方证书。

SSLHandshake适用于自签名证书,但不适用于第三方证书。

任何人都可以告诉为什么?

HttpsNetServer.java

 import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocketFactory; public class HttpsNetServer { public static void main(String args[]) throws Exception { SSLContext context; KeyManagerFactory kmf; KeyStore ks; char[] storepass = "changeit".toCharArray(); char[] keypass = "changeit".toCharArray(); String storename = "/home/krishnan/.keystore"; context = SSLContext.getInstance("TLS"); kmf = KeyManagerFactory.getInstance("SunX509"); FileInputStream fin = new FileInputStream(storename); ks = KeyStore.getInstance("JKS"); ks.load(fin, storepass); kmf.init(ks, keypass); context.init(kmf.getKeyManagers(), null, null); SSLServerSocketFactory ssf = context.getServerSocketFactory(); ServerSocket ss = ssf.createServerSocket(8000); Socket s = ss.accept(); PrintStream out = new PrintStream(s.getOutputStream()); out.println("Hi"); out.close(); s.close(); } } 

HttpsNetClient.java

 import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.security.cert.CertPath; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class HttpsNetClient { public static void main(String args[]) throws Exception { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, // No Key Manager new TrustManager[] { new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} @Override public void checkServerTrusted(X509Certificate[] xcert, String arg1) throws CertificateException { System.out.println("Certificate"); /* for( X509Certificate certificate : xcert) { System.out.println(certificate.toString()); }*/ // check the certs } @Override public X509Certificate[] getAcceptedIssuers() { return null; } } }, // TrustManager null); SSLSocketFactory factory = context.getSocketFactory(); SSLSocket socket = (SSLSocket) factory.createSocket("127.0.0.1", 8000); socket.startHandshake(); SSLSession session = socket.getSession(); java.security.cert.Certificate[] servercerts = session.getPeerCertificates(); List mylist = new ArrayList(); for (int i = 0; i < servercerts.length; i++) { mylist.add(servercerts[i]); } CertificateFactory cf = CertificateFactory.getInstance("X.509"); CertPath cp = cf.generateCertPath(mylist); FileOutputStream f = new FileOutputStream("CertPath.dat"); ObjectOutputStream b = new ObjectOutputStream(f); b.writeObject(cp); } } 

控制台输出

 trigger seeding of SecureRandom done seeding SecureRandom Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 Allow unsafe renegotiation: false Allow legacy hello messages: true Is initial handshake: true Is secure renegotiation: false %% No cached client session *** ClientHello, TLSv1 RandomCookie: GMT: 1388082990 bytes = { 150, 135, 207, 23, 25, 26, 29, 28, 215, 141, 166, 204, 95, 134, 251, 101, 171, 119, 173, 127, 35, 182, 181, 72, 56, 81, 36, 68 } Session ID: {} Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_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, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 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] *** [write] MD5 and SHA1 hashes: len = 163 0000: 01 00 00 9F 03 01 53 BC 77 2E 96 87 CF 17 19 1A ......Sw...... 0010: 1D 1C D7 8D A6 CC 5F 86 FB 65 AB 77 AD 7F 23 B6 ......_..ew.#. 0020: B5 48 38 51 24 44 00 00 38 C0 0A C0 14 00 35 C0 .H8Q$D..8.....5. 0030: 05 C0 0F 00 39 00 38 C0 09 C0 13 00 2F C0 04 C0 ....9.8...../... 0040: 0E 00 33 00 32 C0 07 C0 11 00 05 C0 02 C0 0C C0 ..3.2........... 0050: 08 C0 12 00 0A C0 03 C0 0D 00 16 00 13 00 04 00 ................ 0060: FF 01 00 00 3E 00 0A 00 34 00 32 00 17 00 01 00 ....>...4.2..... 0070: 03 00 13 00 15 00 06 00 07 00 09 00 0A 00 18 00 ................ 0080: 0B 00 0C 00 19 00 0D 00 0E 00 0F 00 10 00 11 00 ................ 0090: 02 00 12 00 04 00 05 00 14 00 08 00 16 00 0B 00 ................ 00A0: 02 01 00 ... main, WRITE: TLSv1 Handshake, length = 163 [Raw write]: length = 168 0000: 16 03 01 00 A3 01 00 00 9F 03 01 53 BC 77 2E 96 ...........Sw. 0010: 87 CF 17 19 1A 1D 1C D7 8D A6 CC 5F 86 FB 65 AB ..........._..e. 0020: 77 AD 7F 23 B6 B5 48 38 51 24 44 00 00 38 C0 0A w..#..H8Q$D..8.. 0030: C0 14 00 35 C0 05 C0 0F 00 39 00 38 C0 09 C0 13 ...5.....9.8.... 0040: 00 2F C0 04 C0 0E 00 33 00 32 C0 07 C0 11 00 05 ./.....3.2...... 0050: C0 02 C0 0C C0 08 C0 12 00 0A C0 03 C0 0D 00 16 ................ 0060: 00 13 00 04 00 FF 01 00 00 3E 00 0A 00 34 00 32 .........>...4.2 0070: 00 17 00 01 00 03 00 13 00 15 00 06 00 07 00 09 ................ 0080: 00 0A 00 18 00 0B 00 0C 00 19 00 0D 00 0E 00 0F ................ 0090: 00 10 00 11 00 02 00 12 00 04 00 05 00 14 00 08 ................ 00A0: 00 16 00 0B 00 02 01 00 ........ [Raw read]: length = 5 0000: 15 03 01 00 02 ..... [Raw read]: length = 2 0000: 02 28 .( 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 Exception in thread "main" 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:1961) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323) at HttpsNetClient.main(HttpsNetClient.java:49) 

不应将第三方证书导入为“mycert”。 这不是你的certificate,而是别人的。 此外,您刚刚破坏了自己的密钥对和证书。 重新开始,使用第三方证书的其他别名。

问题是密钥库必须包含公共证书和私钥。
在第一个示例中,keytool正在创建它们并将它们放入密钥库。
在第二个示例中,您缺少私钥。

你应该做:

  1. 将公共证书和私钥导入pkcs12(* .p12)密钥库
    openssl pkcs12 -export -in mycert.crt -inkey mykey.key \ -out lig.p12 -name some-alias \ -CAfile ca.crt -caname root

  2. 将pkcs12转换为JSK
    keytool -importkeystore \ -deststorepass changeit -destkeypass changeit -destkeystore lig.keystore \ -srckeystore lig.p12 -srcstoretype PKCS12 -srcstorepass some-password \ -alias some-alias

  3. 从您的代码中引用这个新的JKS密钥库

论证解释

mycert.crt – >您的公共证书
mykey.key – >你的私钥
ca.crt – >签署您的公共证书和私钥的证书颁发机构的公共证书

您不能使用该ca.crt来创建p12密钥库,但您应该这样做 。 p12也可以用来容纳它,如果它不存在,你可能会遇到一些库的问题。 无论如何,你可以尝试使用和不使用它; 如果失败,图书馆很可能会非常清楚地告诉你这个问题。
如果您使用的是自签名证书,那么您绝对可以忘记ca.crt参数,并且任何程序都不会给您带来任何问题。 但是,如果我理解得很好,你使用的是第三方证书,所以我的猜测是他们已经为你提供了ca.cert或者.p12包含了所有内容(或者.pfx,它们是相同的)。

如果仍然不清楚,你可以列出他们提供给你的文件,我可以告诉你哪一个是哪个。 我想系统管理员一致地命名文件(他们通常这样做),所以它应该是非常直接的。