【问题标题】:Handshake failure Client Key Exchange, using a certificate chain握手失败客户端密钥交换,使用证书链
【发布时间】:2016-12-07 09:55:21
【问题描述】:

我正在尝试使用 Java 建立到 Web 服务的 2 路 TSL 连接,我获得了一个带有私钥的 pfx 证书和一个由 3 个证书组成的证书链。这是使用spring框架的java代码:

    @Bean
public Client weatherClient(Jaxb2Marshaller marshaller) throws Exception {
    Client client = new Client();
    client.setDefaultUri(".....");
    client.setMarshaller(marshaller);
    client.setUnmarshaller(marshaller);

    KeyStore ks = KeyStore.getInstance("PKCS12");
    ks.load(keyStore.getInputStream(), keyStorePassword.toCharArray());

    LOGGER.info("Loaded keystore: " + keyStore.getURI().toString());
    System.out.println("Loaded keystore: " + keyStore.getURI().toString());

    keyStore.getInputStream().close();


    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());//KeyManagerFactory.getDefaultAlgorithm()
    keyManagerFactory.init(ks, keyStorePassword.toCharArray());

    KeyStore ts = KeyStore.getInstance("PKCS12");
    ts.load(trustStore.getInputStream(), trustStorePassword.toCharArray());//
    LOGGER.info("Loaded trustStore: " + trustStore.getURI().toString());
    System.out.println("Loaded trustStore: " + trustStore.getURI().toString());

    trustStore.getInputStream().close();

    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(ts);

    HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender();
    messageSender.setKeyManagers(keyManagerFactory.getKeyManagers());
    messageSender.setTrustManagers(trustManagerFactory.getTrustManagers()); 
    client.setMessageSender(messageSender);
    return client;
}

到目前为止,我得到了一个 ClientHello 和一个发送证书的 ServerHello,我得到了一个 Found 受信任的证书。然后是一个没有找到任何证书的证书请求

*** CertificateRequest 
Cert Types: RSA, DSS 
Cert Authorities:
<CN=Thawte SSL CA, O="Thawte, Inc.", C=US>
....
....
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client  authentication
*** Certificate chain
<Empty>
***

我已将证书单独添加到 lib/security/cacerts。 似乎第一次证书交换发生在 cacerts 密钥库中,因为如果这是添加证书的唯一位置,我会得到相同的行为。似乎该请求正在寻找证书链,但无法找到它,即使我已作为带有私钥和证书链的 pkcs12 导入 KeyStore 对象。任何帮助将不胜感激

更新

我在 ClientKeyExchange 之后遇到握手失败,我认为这是由于上述警告,但我可能错了。

*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
main, WRITE: TLSv1 Handshake, length = 269
SESSION KEYGEN:
PreMaster Secret:
....
....
0000: B0 E2 38 5E 40 4E 7C C5                            ..8^@N..
Server write IV:
0000: 44 40 45 E1 82 45 15 9B                            D@E..E..
main, WRITE: TLSv1 Change Cipher Spec, length = 1
*** Finished
verify_data:  { 109, 220, 225, 98, 98, 233, 48, 215, 61, 50, 58, 207 }
***
main, WRITE: TLSv1 Handshake, length = 40
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT:  fatal, handshake_failure
%% Invalidated:  [Session-1, SSL_RSA_WITH_3DES_EDE_CBC_SHA]

更新

如果我将密钥库添加为变量-Djavax.net.ssl.keyStore=,则相互身份验证有效 但是如果没有将密钥库添加为变量,我会得到以下信息。找到代码中指定的密钥库和信任库,并在调试中显示证书链和信任库

***
found key for : devcert
chain [0] = [
[
  Version: V3 ......

***
adding as trusted cert:
  Subject: 

然后显示一个空的密钥库,并将 JVM cacerts 用作受信任的证书。

keyStore is : 
keyStore type is : jks
keyStore provider is : 
init keystore
init keymanager of type SunX509
trustStore is: /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts
trustStore type is : jks
trustStore provider is : 
init truststore
adding as trusted cert:
  Subject: CN=ubuntu

然后有一个服务器你好 *** 服务器你好,TLSv1 找到证书的对象

    ***
    Found trusted certificate:
but the Certificate Request does find a matching certificate as above, unless it is added as a variable 
*** CertificateRequest 
Cert Types: RSA, DSS 
Cert Authorities:
<CN=Thawte SSL CA, O="Thawte, Inc.", C=US>
....
....
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client  authentication
*** Certificate chain
<Empty>
***

将密钥库添加为变量-Djavax.net.ssl.keyStore=的行为

*** ServerHelloDone
matching alias: devcert
*** Certificate chain
chain [0] = [
[
  Version: V3

我想使用程序代码中的密钥库和信任库,以便以后能够动态更改它

【问题讨论】:

  • 重新编辑,您将不得不查看服务器 SSL 日志以了解那里出了什么问题。如果客户端发送Certificate消息,则客户端证书有效。
  • 谢谢,知道这很有用,我无权访问服务器,但我猜测客户端密钥交换后的一些数据交换导致错误。也许将错误的数据传递给服务器

标签: java spring ssl keystore truststore


【解决方案1】:

您应该获得私钥。这已经是一个重大的安全漏洞。实际的问题是该证书要么没有由 CertificateRequest 消息中提到的 CA 签名,要么不是其中提到的类型。

【讨论】:

  • 我在磁盘上获得了带有私钥的 .pfx 文件。我可以使用 SoapUI 使用证书连接到服务。证书的类型为密钥算法:RSA
  • 未由 Thawte 签名。
  • 谢谢,我通过浏览器获得了 Thawte 证书并导入了 cacerts 密钥库,没有它我会变得致命,description = certificate_unknown in the serverHello 阶段
猜你喜欢
  • 2016-01-18
  • 2019-02-28
  • 2018-05-15
  • 2016-05-22
  • 2017-08-24
  • 2016-09-16
  • 1970-01-01
  • 2016-07-22
  • 2012-04-28
相关资源
最近更新 更多