本文共 5595 字,大约阅读时间需要 18 分钟。
JSSE(Java Security Socket Extension)是Sun公司为了解决互联网信息安全传输提出的一个解决方案,它实现了SSL和TSL协议,包含了数据加密、服务器验证、消息完整性和客户端验证等技术。通过使用JSSE简洁的API,可以在客户端和服务器端之间通过SSL/TSL协议安全地传输数据。
首先,需要将一文中生成的客户端及服务端私钥和数字证书进行导出,生成Java环境可用的keystore文件。
客户端私钥与证书的导出:
1 2 | openssl pkcs12 - export -clcerts -name www.mydomain.com \ -inkey private /client-key .pem - in certs /client .cer -out certs /client .keystore |
服务器端私钥与证书的导出:
1 2 | openssl pkcs12 - export -clcerts -name www.mydomain.com \ -inkey private /server-key .pem - in certs /server .cer -out certs /server .keystore |
受信任的CA证书的导出:
1 2 | keytool -importcert -trustcacerts - alias www.mydomain.com - file certs /ca .cer \ -keystore certs /ca-trust .keystore |
之后,便会在certs文件夹下生成ca-trust.keystore文件。加上上面生成的server.keystore和client.keystore,certs下会生成这三个文件:
Java实现的SSL通信客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | package com.demo.ssl; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.security.KeyStore; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManagerFactory; public class SSLClient { private SSLSocket sslSocket; public static void main(String[] args) throws Exception { SSLClient client = new SSLClient(); client.init(); System.out.println( "SSLClient initialized." ); client.process(); } //客户端将要使用到client.keystore和ca-trust.keystore public void init() throws Exception { String host = "127.0.0.1" ; int port = 1234 ; String keystorePath = "/home/user/CA/certs/client.keystore" ; String trustKeystorePath = "/home/user/CA/certs/ca-trust.keystore" ; String keystorePassword = "abc123_" ; SSLContext context = SSLContext.getInstance( "SSL" ); //客户端证书库 KeyStore clientKeystore = KeyStore.getInstance( "pkcs12" ); FileInputStream keystoreFis = new FileInputStream(keystorePath); clientKeystore.load(keystoreFis, keystorePassword.toCharArray()); //信任证书库 KeyStore trustKeystore = KeyStore.getInstance( "jks" ); FileInputStream trustKeystoreFis = new FileInputStream(trustKeystorePath); trustKeystore.load(trustKeystoreFis, keystorePassword.toCharArray()); //密钥库 KeyManagerFactory kmf = KeyManagerFactory.getInstance( "sunx509" ); kmf.init(clientKeystore, keystorePassword.toCharArray()); //信任库 TrustManagerFactory tmf = TrustManagerFactory.getInstance( "sunx509" ); tmf.init(trustKeystore); //初始化SSL上下文 context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null ); sslSocket = (SSLSocket)context.getSocketFactory().createSocket(host, port); } public void process() throws Exception { //往SSLSocket中写入数据 String hello = "hello boy!" ; OutputStream out = sslSocket.getOutputStream(); out.write(hello.getBytes(), 0 , hello.getBytes().length); out.flush(); //从SSLSocket中读取数据 InputStream in = sslSocket.getInputStream(); byte [] buffer = new byte [ 50 ]; in.read(buffer); System.out.println( new String(buffer)); } } |
初始化时,首先取得SSLContext、KeyManagerFactory、TrustManagerFactory实例,然后加载客户端的密钥库和信任库到相应的KeyStore,对KeyManagerFactory和TrustManagerFactory进行初始化,最后用KeyManagerFactory和TrustManagerFactory对SSLContext进行初始化,并创建SSLSocket。
Java实现的SSL通信服务器端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | package com.demo.ssl; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.security.KeyStore; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.TrustManagerFactory; public class SSLServer { private SSLServerSocket sslServerSocket; public static void main(String[] args) throws Exception { SSLServer server = new SSLServer(); server.init(); System.out.println( "SSLServer initialized." ); server.process(); } //服务器端将要使用到server.keystore和ca-trust.keystore public void init() throws Exception { int port = 1234 ; String keystorePath = "/home/user/CA/certs/server.keystore" ; String trustKeystorePath = "/home/user/CA/certs/ca-trust.keystore" ; String keystorePassword = "abc123_" ; SSLContext context = SSLContext.getInstance( "SSL" ); //客户端证书库 KeyStore keystore = KeyStore.getInstance( "pkcs12" ); FileInputStream keystoreFis = new FileInputStream(keystorePath); keystore.load(keystoreFis, keystorePassword.toCharArray()); //信任证书库 KeyStore trustKeystore = KeyStore.getInstance( "jks" ); FileInputStream trustKeystoreFis = new FileInputStream(trustKeystorePath); trustKeystore.load(trustKeystoreFis, keystorePassword.toCharArray()); //密钥库 KeyManagerFactory kmf = KeyManagerFactory.getInstance( "sunx509" ); kmf.init(keystore, keystorePassword.toCharArray()); //信任库 TrustManagerFactory tmf = TrustManagerFactory.getInstance( "sunx509" ); tmf.init(trustKeystore); //初始化SSL上下文 context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null ); //初始化SSLSocket sslServerSocket = (SSLServerSocket)context.getServerSocketFactory().createServerSocket(port); //设置这个SSLServerSocket需要授权的客户端访问 sslServerSocket.setNeedClientAuth( true ); } public void process() throws Exception { String bye = "Bye!" ; byte [] buffer = new byte [ 50 ]; while ( true ) { Socket socket = sslServerSocket.accept(); InputStream in = socket.getInputStream(); in.read(buffer); System.out.println( "Received: " + new String(buffer)); OutputStream out = socket.getOutputStream(); out.write(bye.getBytes()); out.flush(); } } } |
先运行服务器端,再运行客户端。服务器端执行结果:
客户端执行结果:
转载地址:http://tmovx.baihongyu.com/