我正在尝试在Java中执行相互身份验证。我想要实现的结构是:具有自签名证书的服务器充当CA,签署客户端证书。因此,这是我在每个密钥库/信任库中保留的内容:
客户端:
密钥库:
信任库:
服务器
密钥库:
信任库:
我能够执行服务器的身份验证,但是当我在服务器上启用setNeedClientAuth(true)时,我在日志中收到以下错误: http://pastebin.com/raw.php?i=P52Qq89z 所以服务器似乎在验证,但客户端无法提供CA链,可能是它的密钥库内容有问题吗?
我使用openSSL生成密钥和证书,KeyStore Explorer创建密钥库(在使用keytool几天后)和JDK 1.7.0_51
更新:按照以下说明解决了问题:https://stackoverflow.com/a/12150604/2891462这是CA自签名证书创建方式的问题(显然只是JDK 1.7中的一个问题)
答案 0 :(得分:3)
您的配置中存在一些错误。
查看调试日志,证书没有基本约束来表示CA = true。
[
Version: V1
Subject: CN=Ficticious bank, OU=SoE, O=University, L=London, ST=England, C=UK
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 2048 bits
Validity: [From: Wed May 07 19:21:23 BST 2014,
To: Thu May 07 19:21:23 BST 2015]
Issuer: CN=Ficticious bank, OU=SoE, O=University, L=London, ST=England, C=UK
SerialNumber: [ 9a7143cf f5ecfbf8]
]
Algorithm: [SHA1withRSA]
...
]
如果它不是CA证书,它将无法作为CA工作。见RFC 3280(和5280):
This extension MUST appear as a critical extension in all CA certificates that contain public keys used to validate digital signatures on certificates.
其次,此证书(您还希望用作服务器的最终实体证书(EEC))并不具有该服务器的有效名称:没有主题备用名称和明显不具有的CN# 39; t匹配任何主机名。虽然默认SSLSocket
默认情况下不进行任何主机名验证(您可以对其进行配置),但拥有服务器证书的有效主机名非常有用,因为客户端应该真正验证它原理
总的来说,对CA和服务器证书使用相同的证书似乎没有多大好处。自签名证书在单独使用时非常有用。如果您还计划将其用作CA证书,则可以将CA证书和服务器证书分开。从长远来看,它肯定是有用的,特别是当您必须更改服务器证书时,在2015年5月7日19:21:23 BST 2015"在您的示例中,或者您可能出于任何其他原因需要重新颁发服务器证书。
除此之外,您对密钥库和信任库有正确的想法:
客户端:
密钥库:
信任库:
服务器
密钥库:
信任库:
答案 1 :(得分:2)
进行相互认证(2路SSL)只需要做两件事
服务器的证书从服务器的密钥库导出(不是信任存储 - 如果您使用不同的信任和密钥库)
,第二个是
客户端的证书应该存在于服务器的信任库中(而不是密钥) 商店 - 如果您使用不同的信任和密钥库)
另外还有一个好的博客here来阅读相同的