ssl/https/wss总结
概念性的东西就不说了,自己去查一下,这里只实践
1. OpenSSL与Java KeyTool的证书
1.1 OpenSSL生成证书的方式总结:
openssl基本原理 + 生成证书 + 使用实例 -这篇很精华,就是格式太差,谁让CSDN没有markdown呢...
如何使用OpenSSL工具生成根证书与应用证书 - 这篇注解写的比较详细
使用OpenSSL API 建立SSL安全通信的一般流程
OpenSSL客户端服务器实例下载 - 使用SSL通信的C++客户端与服务器聊天程序,需要配置OpenSSL的Lib库
1.2 Java KeyTool的使用
JDK 中的证书生成和管理工具 keytool
Java HTTPS客户端如何处理证书 - 这篇文章非常好,关于Java端ssl的使用,基本上看这一篇就够了
1.3 Openssl与Java keytool生成证书的转换
2.Java客户端发送https请求
可参考我之前的一篇总结性文章:
Nginx配置https Java代码单向验证 -包含客户端验证服务器证书与不验证服务器证书两种连接方式
3. Java发送wss(Secure Websocket)请求
3.1 Java-Websocket.jar
java WebSocket的实现以及Spring WebSocket -这篇文章讲了Java各种对WebSocket的实现
然而,上面文章里的实现并不怎么好用,我项目中用的是Java-Websocket的实现:
github地址
Maven仓库地址
3.2 java的websocket客户端连接C++的SSL服务器(单向验证)
Java-Websocket的代码中有对SSL的实现示例,是一个客户端与服务器双向验证的例子,但是用的是同个keystore与truststore
参考Java HTTPS客户端如何处理证书这篇文章中的单向验证部分
server侧只需要自己的keystore文件,不需要truststore文件
client侧不需要自己的keystore文件,只需要truststore文件(其中包含server的公钥)
此外server侧需要在创建SSLServerSocket之后设定不需要客户端证书:setNeedClientAuth(false)
C++客户端与服务器代码上面的链接中都有,这里关键的问题是两点:
- Java使用的是jks格式的证书,C++使用的是pem格式的,双方是否能连通?(理论上没问题,经验证也没问题)
- Java使用的keystore与truststore与C++的证书,私钥有什么对应关系?
- keystore中一般保存的是我们的私钥,用来加解密或者为别人做签名,通过它可以导出证书
- truststore保存的是可信任的证书
我们用OpenSSL来生成证书与私钥,PEM格式证书转换为jks文件:
转换为pkcs12格式:
~/tmp/cert# openssl pkcs12 -export -in public.crt -inkey private.pem -out server.p12 -name server -passin pass:${passwd} -passout pass:${passwd}
~/tmp/cert# ll
total 16
-rw-r--r-- 1 root root 664 Jun 14 20:43 cert.csr
-rw-r--r-- 1 root root 963 Jun 14 20:27 private.pem
-rw-r--r-- 1 root root 871 Jun 14 20:44 public.crt
-rw-r--r-- 1 root root 1682 Jun 14 20:55 server.p12
导入到jks中:
~/tmp/cert# keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass ${passwd} -alias server -deststorepass ${passwd} -destkeypass ${passwd} -destkeystore ServerCert.jks
~/tmp/cert# ll
total 20
-rw-r--r-- 1 root root 664 Jun 14 20:43 cert.csr
-rw-r--r-- 1 root root 963 Jun 14 20:27 private.pem
-rw-r--r-- 1 root root 871 Jun 14 20:44 public.crt
-rw-r--r-- 1 root root 1372 Jun 14 20:57 ServerCert.jks
-rw-r--r-- 1 root root 1682 Jun 14 20:55 server.p12
Java-Websocket客户端代码:
public static void SSLTestSingle1()throws Exception {
WebSocketChatClient chatclient = new WebSocketChatClient( new URI( "wss://localhost:8443" ) );
// load up the key store
String STORETYPE = "JKS";
String KEYSTORE = "foxclienttrust.keystore";
String STOREPASSWORD = "foxclienttrustks";
KeyStore ks = KeyStore.getInstance( STORETYPE );
File kf = new File( KEYSTORE );
ks.load( new FileInputStream( kf ), STOREPASSWORD.toCharArray() );
// KeyManagerFactory kmf = KeyManagerFactory.getInstance( "SunX509" );
// kmf.init( ks, KEYPASSWORD.toCharArray() );
TrustManagerFactory tmf = TrustManagerFactory.getInstance( "SunX509" );
tmf.init( ks );
SSLContext sslContext = null;
sslContext = SSLContext.getInstance( "TLS" );
sslContext.init( null, tmf.getTrustManagers(), null );
// sslContext.init( null, null, null ); // will use java's default key and trust store which is sufficient unless you deal with self-signed certificates
SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault();
chatclient.setSocket( factory.createSocket() );
chatclient.connectBlocking();
BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) );
while ( true ) {
String line = reader.readLine();
if( line.equals( "close" ) ) {
chatclient.close();
} else {
chatclient.send( line );
}
}
}