如何在 java 中进行相互 SSL 身份验证

How to do mutual SSL authentication in java

我想使用 java 代码进行相互 SSL 身份验证,但我没有成功 我有 key.pemcert.pem 文件来进行身份验证 我已经尝试使用 Curl

curl -X POST -d '{ "Channel": "....}' -H "Content-Type: application/json" -H "Auth1: ***" -H "Auth2: ***" -k https://******/webservices/JSON/Default.aspx --cert "cert.pem" --key "Key.pem"

它运行良好,然后我尝试创建 java 程序参考 但是服务器 returns "CERT_MISSING"。我也试过这个 https://www.naschenweng.info/2018/02/01/java-mutual-ssl-authentication-2-way-ssl-authentication/ 这个代码创建 p12,crt 和 jks 文件,如上所述 link 但仍然得到同样的错误 "CERT_MISSING"。 这是有效的 NodeJS 示例:

var https = require("https");
var fs = require("fs");

var jsonData = {
    "Channel": ....
}

var options = {
    hostname: "****",
    port: 443,
    path: '/webservices/JSON/Default.aspx',
    method: 'POST',
    timeout: this.TimeOut,
    headers: {'Content-Type':'application/json',"Auth1": "****","Auth2": "*****"},
    json: true,
    key: fs.readFileSync('Key.pem'),
    cert: fs.readFileSync('cert.pem')
}

var req = https.request(options, function(res) {
    res.on('data', function(data) {
        var response = JSON.parse(data)
            console.log(response)

            req.end();
    });
});
req.on('error', function(e) {
    console.log("ERROR:");

    })


req.write(JSON.stringify(jsonData));
req.end();

请帮帮我。

我只是想尝试回忆一些事情来完成你的清单。我无法举出完整的例子。我假设您同时控制客户端和服务器代码。或者至少是客户端代码,以及服务器配置的全面调整。

0-用wireshark看看是怎么回事。

1-确保您的服务器端在 serverhello 中发送了 accept-client-cert 或 requires-client-cert。 Curl 可能工作只是因为服务器不是 "requiring" 它,只是请求它。

2-确保服务器信任您的客户端证书签名者。这意味着如果您要在测试时制作自签名客户端证书,有时会破解服务器的证书颁发机构 (CA) 存储。

3-使用 wireshark,观察 ssl/tls 对话框并验证 clienthello 和 serverhello 是否符合预期(主要是如果 serverhello 执行 request/require 客户端身份验证并且客户端甚至尝试发送它)。如果有的话,那是很有教育意义的。

4-使用 jsse 教程自下而上编写琐碎的代码。使代码卡塔看到 keystore/castore 在那里,包含你所期望的。然后继续进行安全 [server]socketfactory 设置、keymanager、trustmanager 和 hostnameverifier(有或没有有人敢建议的后两者的危险绕过)。设置好这 4 个部分后,您就完成了 99%,您的 ssl/tls 套接字应该可以工作了。通常仍然会阻止您进行 ssl/tls 连接的少数事情是不兼容的密码套件或 tls 版本,或者具有无效日期的证书。由于您同时控制客户端和服务器,因此这应该不是问题。

5-一旦您可以信任您的客户端行为,您可以尝试连接到 https 服务器,例如 tomcat 或码头(我不知道您使用的是什么),并在 sslsocket 上发送粗略的 GET你 java 客户。

6-如果可行,现在您可以将 sslsocketfactory 传递给许多 http[s] 堆栈(smtp、httplient,甚至核心 jdk httpurlconnection)。

我认为您需要 "internediate-cert" 文件来将所有证书连接到一个 PEM 文件中,例如 cat "internediate-cert.pem" "codika_cert.pem" "Key.pem" > full-chain.keycert.pem 然后使用别名和密码生成 PKCS12(.p12) 密钥库 Like pkcs12 -export -in "full-chain.keycert.pem" -out full-chain.keycert.p12 -name alias -noiter -nomaciter 然后使用 full-chain.keycert.p12 作为密钥库和密码。它应该工作。