为什么java在SSL握手期间不发送客户端证书? [英] why doesn't java send the client certificate during SSL handshake?

查看:47
本文介绍了为什么java在SSL握手期间不发送客户端证书?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试连接到安全的网络服务.

I'm trying to connect to a secure webservice.

即使我的密钥库和信任库设置正确,我还是出现了握手失败.

I was getting a handshake failure even though my keystore and truststore have been set correctly.

经过几天的挫折,无休止的谷歌搜索并询问周围的每个人,我发现唯一的问题是java在握手期间选择不将客户端证书发送到服务器.

After several days of frustration, endless googling and asking everyone around I found out that the only problem was that java chose not to send the client certificate to the server during the handshake.

特别是:

  1. 服务器请求客户端证书 (CN=RootCA) - 即给我一个由根 CA 签名的证书"
  2. Java 查看了密钥库,只找到了我的客户端证书,该证书由SubCA"签名,而该证书又由RootCA"颁发.没有费心去查看信任库......好吧,我猜
  3. 遗憾的是,当我尝试将SubCA"证书添加到密钥库时,这根本没有帮助.我确实检查了证书是否已加载到密钥库中.他们会这样做,但 KeyManager 会忽略除客户端证书之外的所有证书.
  4. 以上所有导致java决定它没有任何满足服务器请求的证书并且什么都不发送...tadaaa握手失败:-(

我的问题:

  1. 是否有可能我以破坏证书链"或其他方式将SubCA"证书添加到密钥库,以便 KeyManager 仅加载客户端证书而忽略其余证书?(Chrome 和 openssl 设法解决了这个问题,那么为什么 java 不能?-请注意,SubCA"证书始终作为受信任的机构单独显示,因此 Chrome 在握手期间显然正确地将其与客户端证书一起打包)
  2. 这是服务器端的正式配置问题"吗?服务器是第三方.我希望服务器请求由SubCA"机构签署的证书,因为这是他们提供给我们的.我怀疑这在 Chrome 和 openssl 中有效的事实是因为它们限制较少",而 java 只是按照书本"而失败.

我确实设法为此制定了一个肮脏的解决方法,但我对此不太满意,所以如果有人能为我澄清这一点,我会很高兴.

I did manage to put together a dirty workaround for this, but I'm not very happy about it so I'll be glad if anyone can clarify this one for me.

推荐答案

您可能已将中间 CA 证书导入密钥库,而未将其与您拥有客户端证书及其私钥的条目相关联.您应该能够使用 keytool -v -list -keystore store.jks 看到这一点.如果您只为每个别名条目获得一个证书,则它们不在一起.

It's possible that you may have imported the intermediate CA certificate into the keystore without associating it with the entry where you have your client certificate and its private key. You should be able to see this using keytool -v -list -keystore store.jks. If you only get one certificate per alias entry, they're not together.

您需要将您的证书及其链一起导入到拥有您的私钥的密钥库别名中.

You would need to import your certificate and its chain together into the keystore alias that has your private key.

要找出哪个密钥库别名具有私钥,请使用 keytool -list -keystore store.jks(我在这里假设是 JKS 存储类型).这会告诉你类似这样的事情:

To find out which keystore alias has the private key, use keytool -list -keystore store.jks (I'm assuming JKS store type here). This will tell you something like this:

Your keystore contains 1 entry

myalias, Feb 15, 2012, PrivateKeyEntry, 
Certificate fingerprint (MD5): xxxxxxxx

这里的别名是myalias.如果除此之外还使用 -v,您应该看到 Alias Name: myalias.

Here, the alias is myalias. If you use -v in addition to this, you should see Alias Name: myalias.

如果您还没有单独拥有它,请从密钥库中导出您的客户端证书:

If you don't have it separately already, export your client certificate from the keystore:

keytool -exportcert -rfc -file clientcert.pem -keystore store.jks -alias myalias

这应该会给你一个 PEM 文件.

This should give you a PEM file.

使用文本编辑器(或 cat),准备文件(我们称之为 bundle.pem)与该客户端证书和中间 CA 证书(可能还有根证书)CA 证书本身(如果需要),以便客户端证书位于开头,其颁发者证书位于下方.

Using a text editor (or cat), prepare file (let's call it bundle.pem) with that client certificate and the intermediate CA certificate (and possibly the root CA certificate itself if you want), so that the client-certificate is at the beginning and its issuer cert is just under.

这应该是这样的:

-----BEGIN CERTIFICATE-----
MIICajCCAdOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVSzEa
....
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICkjCCAfugAwIBAgIJAKm5bDEMxZd7MA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
....
-----END CERTIFICATE-----

现在,将此包一起导入到您的私钥所在的别名中:

Now, import this bundle back together into the alias where your private key is:

keytool -importcert -keystore store.jks -alias myalias -file bundle.pem

这篇关于为什么java在SSL握手期间不发送客户端证书?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆