Java使用SSLSocket通信-阿里云开发者社区

开发者社区> 小龙猫> 正文

Java使用SSLSocket通信

简介:
+关注继续查看

JSSE(Java Security Socket Extension)是Sun公司为了解决互联网信息安全传输提出的一个解决方案,它实现了SSL和TSL协议,包含了数据加密、服务器验证、消息完整性和客户端验证等技术。通过使用JSSE简洁的API,可以在客户端和服务器端之间通过SSL/TSL协议安全地传输数据。

首先,需要将OpenSSL生成根证书CA及签发子证书一文中生成的客户端及服务端私钥和数字证书进行导出,生成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

191952_1nzY_1434710.png

服务器端私钥与证书的导出:

1
2
openssl pkcs12 -export -clcerts -name www.mydomain.com \
-inkey private/server-key.pem -in certs/server.cer -out certs/server.keystore

192440_poCJ_1434710.png

受信任的CA证书的导出:

1
2
keytool -importcert -trustcacerts -alias www.mydomain.com -file certs/ca.cer \
-keystore certs/ca-trust.keystore

200735_n3mV_1434710.png

之后,便会在certs文件夹下生成ca-trust.keystore文件。加上上面生成的server.keystore和client.keystore,certs下会生成这三个文件:

201315_VnzM_1434710.png

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();
        }
    }
}

先运行服务器端,再运行客户端。服务器端执行结果:

200138_0HVg_1434710.png

客户端执行结果:

201752_YeZK_1434710.png

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Bash socket programming with /dev/tcp(大家能联想到怎么使用吗)
http://pangty.ta139.com/bash-guide/abs3.7cnhtm/devproc.
711 0
【Java】使用javaassist修改jar包
由于工作需要,可能会涉及到一些需要对第三方的一些jar包与源码进行修改的情况,这个时候javaassist就可以派上用场。 javaassist是一个开源的编辑、修改、创建字节码的类库,它在JBoos项目的AOP框架中发挥了很大的作用。不过我们这次仅仅使用它的修改class的功能。 1 准备工具 1.1 需要用到的工具 1.javaassist.jar 修改class字节码,修改类
6952 0
Java Class类的使用 和 动态加载类
Class类 1)在面向对象的世界里,万事万物皆对象。 类是对象,类是java.lang.Class类的实例对象。 There is a class named Class 2)Foo的实例对象如何表示 Foo foo1=new Foo();//foo1就表示出来了 ...
633 0
Java 使用轮询获取线程返回数据
本文目录 1. 多线程的特点 2. 使用轮询强制等待 3. 轮询的弊端 4. 小结
9 0
MSSQL - 最佳实践 - 使用SSL加密连接
--- title: MSSQL - 最佳实践 - 使用SSL加密连接 author: 风移 --- # 摘要 在SQL Server安全系列专题月报分享中,往期我们已经陆续分享了:[如何使用对称密钥实现SQL Server列加密技术](http://mysql.taobao.org/monthly/2018/08/03/)、[使用非对称密钥实现SQL Server列加密](http:/
2510 0
java使用阿里云短信服务发送短信验证码
java使用阿里云短信服务发送短信验证码
105 0
c# Process类使用小例
  公司为了安全方面的考虑,对员工使用的window操作系统做了权限限制。如果我们想在自己使用的机器上安装额外的软件,就需要找系统管理员!感觉是相当的不爽啊!   但是为了我们这些程序员正常工作,允许我们用管理员的权限运行vs2010,这就为我们间接获得管理员权限安装自己想要的软件留下了后门。
576 0
+关注
125
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载