gpt4 book ai didi

java - 通过 Java 的 SSL 套接字连接

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:57:44 24 4
gpt4 key购买 nike

看了很多关于这些主题的答案,我发现自己完全无法把拼图的各个部分拼起来,还望大家见谅。

我正在尝试将 Java 中的简单套接字连接更改为使用 SSL。如果可能,我希望服务器和客户端都对自己进行身份验证,但只有服务器身份验证才是好的开始。

目前,这是服务器端极其简单的代码:

    ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();

这是客户端的代码:

    Socket socket = null;
while (true) {
try {
socket = new Socket(ipAddress, port);
break;
} catch (Exception e) {}
}

这工作正常,但没有 SSL。

我已经使用 OpenSSL 为服务器和客户端生成了 SSL 证书,最后是:

  • 服务器证书(PEM 格式)
  • 客户端证书(PEM 格式)
  • 服务器的私钥(PEM 格式)
  • 客户端的私钥(PEM 格式)
  • CA 文件(PEM、CER 和 CRT 格式)

据此,我使用 OpenSSL 为客户端和服务器创建了 PKCS12 (.p12) keystore ,如下所示

  • server.p12,通过 openssl pkcs12 -export -in server-cert.pem -inkey server-private-key.pem -out server.p12
  • client.p12,通过 openssl pkcs12 -export -in client-cert.pem -inkey client-private-key.pem -out client.p12

然后,我使用 keytool 将它们转换为 JKS keystore (例如,对于服务器,命令是 keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore server.jks -deststoretype JKS),导致两个文件名为 server.jksclient.jks

然后我使用以下代码替换之前的服务器代码段:

    char[] keyStorePassword =  "JKSPassword".toCharArray();
FileInputStream keyStoreFile = new FileInputStream("somepath/server.jks");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(keyStoreFile, keyStorePassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "PKCS12Password".toCharArray());
SSLContext sslContext = SSLContext.getDefault();
ServerSocket serverSocket = sslContext.getServerSocketFactory().createServerSocket(port);
Socket socket = serverSocket.accept();

以及以下代码作为客户端代码段的替换:

    Socket socket = null;
while (true) {
try {
char[] keyStorePassword = "JKSPassword".toCharArray();
FileInputStream keyStoreFile = new FileInputStream("somepath/client.jks");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(keyStoreFile, keyStorePassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "PKCS12Password".toCharArray());
SSLContext sslContext = SSLContext.getDefault();
socket = sslContext.getSocketFactory().createSocket(ipAddress, port);
break;
} catch (Exception e) {}
}

我现在仍然在服务器上得到javax.net.ssl.SSLHandshakeException: no cipher suites in common(和javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 在客户端上)。

有什么问题吗?

最佳答案

我找到了拼图缺失的部分(我相信)。

我在客户端上放置了 SSLContext sslContext = SSLContext.getDefault(); 行,而不是:

    BufferedInputStream serverCertificateFile = new BufferedInputStream(new FileInputStream("somepath/server-cert.der"));
X509Certificate serverCertificate = (X509Certificate)
CertificateFactory.getInstance("X.509").generateCertificate(serverCertificateFile);
sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
throw new CertificateException();
}
@Override
public void checkServerTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
boolean valid = false;
for (X509Certificate certificate : arg0) {
try {
certificate.verify(serverCertificate.getPublicKey());
valid = true;
break;
} catch (SignatureException e) {}
}
if (!valid) {
throw new CertificateException();
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}, new SecureRandom());

server-cert.der 是一个文件,使用 openssl509 -outform der -in server-cert.pem -out server-cert.der 创建。

我无法在 StackOverflow 上找到关于此事的好的教程或问题,所以这是我通过尝试理解引用指南而创建的。

本质上,我正在为服务器创建一个 TrustManager,当提供的证书之一属于您自己的服务器时,它会信任它。

它似乎有效,请让我知道这种方法是否有任何主要错误(不幸的是我假设有)。感谢阅读这么多!

关于java - 通过 Java 的 SSL 套接字连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32378824/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com