Java客户端证书和密钥库

时间:2015-06-16 17:53:16

标签: java ssl https ssl-certificate

我们正在尝试构建一个MUTUAL / 2WAY认证机制。

因为我们点击了两个不同的主机,所以我们在客户端密钥库容器中存储了两个不同别名下的相同客户端证书(请注意相同的指纹):

root@perf-golem-4:/opt/golem# keytool -list -keystore ./client.keystore -storepass ________

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 2 entries

i.domain.io, Jun 16, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): 28:94:45:A1:78:C0:BD:D6:82:7E:09:66:15:11:8D:A5:56:0B:99:39
r.domain.io, Jun 16, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): 28:94:45:A1:78:C0:BD:D6:82:7E:09:66:15:11:8D:A5:56:0B:99:39

现在,在受信任的容器下,我们有目标域证书(请注意它们之间的指纹是如何不同的,并且还与上面的密钥库进行比较):

root@perf-golem-4:/opt/golem# keytool -list -keystore ./trusted.keystore -storepass _______

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 2 entries

i.domain.io, Jun 16, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): 73:F5:96:68:89:56:5E:50:9C:06:69:67:AC:8E:18:D2:D9:C1:33:71
r.domain.io, Jun 16, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): 12:93:C8:41:3F:68:22:8F:40:F8:3C:B9:B6:C4:90:C0:60:49:D0:50

我的理解是,如果你必须存储一个带有与目标域名匹配的别名的证书(在我们的例子中是i.domain.io或r.domain.io),那么java可以提供相关的证书作为客户端证书。您正在尝试与该域的SSL连接,例如https://r.domain.io

我们正在推出这样的应用程序:

java    -Djavax.net.debug=all \
        -Djavax.net.ssl.keyStore=/opt/golem/client.keystore \
        -Djavax.net.ssl.keyStorePassword=_____ \
        -Djavax.net.ssl.trustStore=/opt/golem/trusted.keystore \
        -Djavax.net.ssl.trustStorePassword=_____ \

我们的问题是没有提供客户端证书,也没有从客户端使用,因此,最大的问题是java是否提供与目标域名(或目标SSL证书中的主题行)匹配的别名相关联的客户端证书)或证书的名称应该从代码中被破坏?

1 个答案:

答案 0 :(得分:2)

  

我的理解是,如果你必须存储一个带有与目标域名匹配的别名的证书(在我们的例子中是i.domain.io或r.domain.io),那么java可以提供相关的证书作为客户端证书。您正在尝试与该域的SSL连接,例如https://r.domain.io

根本不是这样。

匹配基于certificate_authorities list sent by the server in its TLS CertificateRequest message(发行人)和密钥类型(例如RSA或DSA)。如果属性不尽如人意,可以选择一些不完美的匹配(请参阅this answer),但您至少希望服务器通告的CA颁发您的客户端证书(通常这样做)在配置它愿意接受的CA证书时自动在服务器端,除非您明确更改其中的配置。

如果需要中间证书,您当然希望确保imported the full chain

基本上,在密钥库中没有两倍相同的证书。

(您可以尝试通过扩展自己的X509KeyManager来强制使用特定的别名,但这还不够;特别是,这不会让服务器请求它,也不会使连锁有效。)

您需要确保将服务器配置为请求证书。这有时可以通过重新协商来完成,因此使用Wireshark可能不一定可以看到CertificateRequest TLS消息。但是,您应该可以使用-Djavax.net.debug=ssl(或all)从客户端查看它:如果您在页面上搜索CertificateRequest,则official documentation for Debugging SSL/TLS Connections会有一个示例。

然后,您需要确保您的证书(或客户端上链的顶部,如果有中间证书)是由CertificateRequest消息中公布的其中一个CA颁发的(发行人DN必须匹配)。

(如果CertificateRequest中的证书颁发机构列表为空,但仍然发送了CertificateRequest消息,则客户端将默认发送它在密钥库中找到的第一个证书。这种情况是非典型的,因为它通常需要在服务器端进行自定义配置。)