在阅读了许多关于这些话题的答案后,我发现自己完全无法将拼图的碎片串在一起,希望您能原谅我。
我正在尝试将Java中简单的socket连接改为使用SSL。如果可能的话,我希望服务器和客户端都能进行身份验证,但仅对服务器进行身份验证将是一个好的开始。
目前,在服务器端,这是极其简单的代码:
以下代码可用作客户端片段的替代方案:
我正在尝试将Java中简单的socket连接改为使用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)密钥库,步骤如下:
- 通过执行openssl pkcs12 -export -in server-cert.pem -inkey server-private-key.pem -out server.p12创建server.p12
- 通过执行openssl pkcs12 -export -in client-cert.pem -inkey client-private-key.pem -out client.p12创建client.p12
然后,我使用keytool将这些文件转换为JKS密钥库(例如,对于服务器,命令为keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore server.jks -deststoretype JKS),结果得到两个文件: server.jks和client.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)。
可能出了什么问题?