首页 文章

为什么java握手期间java不发送客户端证书?

提问于
浏览
55

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

即使我的密钥库和信任库已正确设置,我也会收到握手失败 .

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

特别:

  • 服务器请求客户端证书(CN = RootCA) - 即"give me a cert that is signed by the root CA"

  • Java查看了密钥库,只发现了我的客户端证书,该证书由"SubCA"签名,而"SubCA"又由"RootCA"签发 . 它没有费心去查看信任库...呃好吧我猜

  • 可悲的是,当我尝试将"SubCA"证书添加到密钥库时,这根本没有帮助 . 我确实检查了证书是否加载到密钥库中 . 他们这样做,但KeyManager忽略除客户端之外的所有证书 .

  • 以上所有导致java决定它没有't have any certificates that satisfy the server'的请求并且什么也没发送... tadaaa握手失败:-(

我的问题:

  • 是否有可能以"broke the certificate chain"或某种方式将"SubCA"证书添加到密钥库中,以便KeyManager仅加载客户端证书而忽略其余证书? (Chrome和openssl设法弄清楚为什么不能用java? - 请注意"SubCA"证书总是作为可信任的权限单独提供,因此Chrome显然在握手期间正确地将其与客户端证书一起打包)

  • 这是服务器端的正式"configuration issue"吗?服务器是第三方 . 我希望服务器能够请求由"SubCA"权威机构签署的证书,因为这是他们为我们提供的 . 我怀疑这个在Chrome和openssl中工作的事实是因为它们是"less restrictive"而java只是"by the book"并且失败了 .

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

2 回答

  • 5

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

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

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

    Your keystore contains 1 entry
    
    myalias, Feb 15, 2012, PrivateKeyEntry, 
    Certificate fingerprint (MD5): xxxxxxxx
    

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

    如果您尚未单独使用它,请从密钥库导出客户端证书:

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

    这应该给你一个PEM文件 .

    使用文本编辑器(或 cat ),准备文件(让我们称之为 bundle.pem )与该客户端证书和中间CA证书(如果需要,可能还有根CA证书本身),以便客户端证书在开头,它的发行人证书就在 .

    这应该是这样的:

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

    现在,将此捆绑包重新导入到私钥所在的别名中:

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

    作为此处的添加,您可以使用%> openssl s_client -connect host.example.com:443并查看转储并检查所有主证书是否对客户端有效 . 您正在输出的底部寻找此信息 . Verify return code: 0 (ok)

    如果添加-showcerts,它将转储与主机证书一起发送的钥匙串的所有信息,这是您加载到钥匙串中的信息 .

相关问题