无法从外部证书创建 SSLContext

Posted

技术标签:

【中文标题】无法从外部证书创建 SSLContext【英文标题】:Unable to create SSLContext from external certificate 【发布时间】:2016-10-04 12:32:19 【问题描述】:

我正在尝试创建自己的 HTTPS 服务器,我有两个代码 sn-ps:

第一个:

private SSLContext createSSLContext() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException, NoSuchProviderException 
    KeyStore keyStore = KeyStore.getInstance("JKS");
    keyStore.load(new FileInputStream("c:\\tmp\\clientkeystore.jks"), "123456".toCharArray());

    // Create key manager
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
    keyManagerFactory.init(keyStore, "123456".toCharArray());
    KeyManager[] km = keyManagerFactory.getKeyManagers();

    // Create trust manager
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
    trustManagerFactory.init(keyStore);
    TrustManager[] tm = trustManagerFactory.getTrustManagers();

    // Initialize SSLContext
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(km, tm, null);

    return sslContext;

第二个:

private SSLContext createSSLContext2() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException, NoSuchProviderException 
    String path = "c:/tmp/example.crt2";
    byte[] certbytes = Files.readAllBytes(Paths.get(path));

    ByteArrayInputStream derInputStream = new ByteArrayInputStream(certbytes);
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream);
    String alias = cert.getSubjectX500Principal().getName();

    KeyStore trustStore = KeyStore.getInstance("JKS");
    trustStore.load(null, "".toCharArray());
    trustStore.setCertificateEntry(alias, cert);
    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    kmf.init(trustStore, null);
    KeyManager[] keyManagers = kmf.getKeyManagers();

    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
    tmf.init(trustStore);
    TrustManager[] trustManagers = tmf.getTrustManagers();

    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(keyManagers, trustManagers, null);
    return sslContext;

第一个 sn-p 一切正常,但是,我想获得更多 - 我为我的本地域创建了自签名 SSL 证书并将其保存在外部文件中。当我尝试使用该证书(example.crt2)时,出现以下异常:

javax.net.ssl.SSLHandshakeException:没有共同的密码套件 在 sun.security.ssl.Alerts.getSSLException(Alerts.java:192) 在 sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) 在 sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) 在 sun.security.ssl.Handshaker.fatalSE(Handshaker.java:292)

curl 的完整输出是:

$ curl -k -vvv https://example.org:443 * 重建 URL 至:https://example.org:443/ * 不支持名称查询超时 * 尝试 127.0.0.1... * 连接到 example.org (127.0.0.1) 端口 443 (#0) * ALPN,提供 http/1.1 * 密码选择:ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * 成功设置证书验证位置: * CAfile:C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt CApath:无 * TLSv1.2 (OUT)、TLS 标头、证书状态 (22): * TLSv1.2 (OUT)、TLS 握手、Client hello (1): * TLSv1.2 (IN),TLS 标头,未知 (21): * TLSv1.2 (IN), TLS alert, Server hello (2): * 错误:14077410:SSL 例程:SSL23_GET_SERVER_HELLO:sslv3 警报握手失败 * 关闭连接 0 curl:(35)错误:14077410:SSL例程:SSL23_GET_SERVER_HELLO:sslv3警报握手失败

clientkeystore.jks 中的证书由以下命令行生成:

keytool -genkey ...

第二个 sn-p 的证书是通过 openssl 生成的:

$ openssl version -a
OpenSSL 1.0.2e 3 Dec 2015
built on: reproducible build, date unspecified
platform: mingw64
options:  bn(64,64) rc4(16x,int) des(idx,cisc,2,long) idea(int) blowfish(idx)
compiler: gcc -I. -I.. -I../include -I/mingw64/include -D_WINDLL -DOPENSSL_PIC -DZLIB_SHARED -DZLIB -DOPENSSL_THREADS -D_MT -DDSO_WIN32 -DL_ENDIAN -O3 -Wall -DWIN32_LEAN_AND_MEAN -DUNICODE -D_UNICODE -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
OPENSSLDIR: "/mingw64/ssl"

我做错了什么?请帮忙!

【问题讨论】:

no shared cipher 可能表明 EC 密钥存在问题,并且使用域参数而不是命名曲线。另请参阅 OpenSSL wiki 上的 Elliptic Curve Cryptography | Named Curves。您需要提供导致问题的证书才能确定这是否是问题所在。 【参考方案1】:

在第二种情况下,没有私钥,只有证书。您需要使用包含私钥条目的 TrustStore 来初始化 KeyManager。

无论如何,你所做的一切都毫无意义。您不能将同一文件同时用作 KeyStore 和信任库。这没有任何意义。

【讨论】:

以上是关于无法从外部证书创建 SSLContext的主要内容,如果未能解决你的问题,请参考以下文章

无法从 xcode 创建新的配置文件

PHONEGAP - 无法导入证书 - IOS

我们应该为外部 https 服务处理证书/公钥固定吗?

Netezza 从外部文件导入错误:不支持的外部表引用,无法导出形状

无法从创建它的方法外部访问 C-Array 元素

如何下载通过CloudFormation创建的IoT证书?