终于设法解决了所有问题,所以我会回答我自己的问题。这些是我用来解决特定问题的设置/文件;
该客户端的密钥库是一个PKCS#12格式文件包含
- 客户端的公共证书(在这种情况下,由自签名CA签名)
- 客户端的私有密钥
为了生成它,我使用了OpenSSL的pkcs12命令。
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "Whatever"
提示:确保获得最新的OpenSSL,而不是版本0.9.8h,因为这似乎存在一个错误,使您无法正确生成PKCS#12文件。
当服务器明确要求客户端进行身份验证时,Java客户端将使用此PKCS#12文件向服务器提供客户端证书。有关客户端证书认证协议实际工作原理的概述,请参见TLS上的Wikipedia文章(在此处还说明了为什么需要客户端的私钥)。
所述客户机的信任是直向前JKS格式包含该文件的根或中间CA证书。这些CA证书将确定您将被允许与哪些端点进行通信,在这种情况下,它将允许您的客户端连接到提供由信任库的CA之一签名的证书的任何服务器。
要生成它,您可以使用标准的Java键盘工具,例如;
keytool -genkey -dname "cn=CLIENT" -alias truststorekey -keyalg RSA -keystore ./client-truststore.jks -keypass whatever -storepass whateverkeytool -import -keystore ./client-truststore.jks -file myca.crt -alias myca
使用此信任库,您的客户端将尝试与所有提供由标识的CA签名的证书的服务器进行完整的SSL握手myca.crt。
上面的文件仅适用于客户端。当您还想设置服务器时,服务器需要自己的密钥和信任库文件。在此网站上可以找到有关为Java客户端和服务器(使用Tomcat)设置完全正常工作的示例的出色演练。
问题/备注/提示
- 客户端证书身份验证只能由服务器强制执行。
- (重要提示!)当服务器请求客户端证书(作为TLS握手的一部分)时,它还将在证书请求中提供受信任CA的列表。如果您希望提供的用于身份验证的客户端证书没有被这些CA之一签名,则根本不会提供(我认为这是很奇怪的行为,但是我确定是有原因的)。这是导致我出现问题的主要原因,因为另一方未正确配置其服务器以接受我的自签名客户端证书,并且我们认为问题出在我端,原因是未在请求中正确提供客户端证书。
- 获取Wireshark。它具有出色的SSL / HTTPS数据包分析功能,将有助于调试和发现问题。-Djavax.net.debug=ssl如果您对Java SSL调试输出不满意,它类似于但更结构化(并且可以说)更易于解释。
- 完全有可能使用Apache httpclient库。如果要使用httpclient,只需用等效的HTTPS替换目标URL,然后添加以下JVM参数(与其他任何客户端相同,无论您要使用哪个库通过HTTP / HTTPS发送/接收数据) :
-Djavax.net.debug=ssl-Djavax.net.ssl.keyStoreType=pkcs12-Djavax.net.ssl.keyStore=client.p12-Djavax.net.ssl.keyStorePassword=whatever-Djavax.net.ssl.trustStoreType=jks-Djavax.net.ssl.trustStore=client-truststore.jks-Djavax.net.ssl.trustStorePassword=whatever



