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

时间:2014-07-08 22:58:36

标签: java ssl https openssl keytool

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

我有一个奇怪的错误。

当我生成证书并添加该密钥库时,我能够进行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  ......S.w.......
0010: 1D 1C D7 8D A6 CC 5F 86   FB 65 AB 77 AD 7F 23 B6  ......_..e.w..#.
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  ...........S.w..
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)

2 个答案:

答案 0 :(得分:1)

第三方证书不应作为&#39; mycert&#39;导入。它不是你的证明,而是别人的证明。此外,您刚刚破坏了自己的密钥对和证书。重新开始,使用第三方证书的其他别名。

答案 1 :(得分:0)

问题是密钥库必须包含公共证书和私钥 在第一个示例中,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. 请从您的代码

  4. 中引用此新的JKS密钥库


    参数说明

    mycert.crt - &gt;你的公共证书
    mykey.key - &gt;你的私钥
    ca.crt - &gt;签署公共证书和私钥的证书颁发机构的公共证书

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

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