tcp ssl java_SSL的TCP通信

该博客展示了如何使用Java实现基于SSL的TCP安全通信。通过详细代码示例,包括服务器端和客户端的配置,解释了如何设置SSLContext,创建SSLServerSocket和SSLSocket,以及如何处理证书和秘钥。内容涵盖了证书的创建、导入和导出,以及客户端和服务器端的交互过程。
摘要由CSDN通过智能技术生成

一切尽在代码中,额。自己測试的小样例。感觉非常实用,做个记录。

server端:

package com.mpc.test.clazz;

import java.io.BufferedReader;

import java.io.FileInputStream;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

import java.security.KeyStore;

import java.security.SecureRandom;

import javax.net.ssl.KeyManagerFactory;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLServerSocket;

import javax.net.ssl.SSLServerSocketFactory;

import javax.net.ssl.TrustManagerFactory;

public class SSLTest {

public static void main(String[] args) throws Exception {

String key = "d:/keys/m.jks";// 定义server端要使用的证书

String trust = "d:keys/trustclient.jks";// 定义server端要信任的证书

/* 个人感觉。上面这两个属性在使用的时候全然能够定义为properties文件或者xml文件来使用 */

KeyStore keyStore = KeyStore.getInstance("JKS");// 定义一个KeyStore用来存储server的秘钥文件

keyStore.load(new FileInputStream(key), "123456".toCharArray());// 载入server端使用的证书,当然要输入要打开加密文件的password了

KeyStore trustStore = KeyStore.getInstance("JKS");// 定义一个KeyStore用来存储server信任的证书文件

trustStore.load(new FileInputStream(trust), "123456".toCharArray());// 载入server端信任的证书文件,当然也要输入password的

/** 额,事实上keyStore和truststore都是Keystore的大家都看到了,就是保存的秘钥文件不同而已了 */

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory

.getDefaultAlgorithm());/*

* 创建一个server的秘钥管理工厂,KeyManagerFactory.

* getDefaultAlgorithm

* ()是指定的默认的算法,记得是RSA··输出一下就OK了

*/

kmf.init(keyStore, "mipengcheng".toCharArray());/*

* 初始化。在初始化的时候须要自定秘钥的password,

* 这个在创建的时候指定的

*/

TrustManagerFactory tmf = TrustManagerFactory

.getInstance(TrustManagerFactory.getDefaultAlgorithm());/*

* 创建一个server信任证书的管理工厂

* ,

* 相同指定了RSA的算法

*/

tmf.init(trustStore);/* 初始化。因为信任的是证书,不是秘钥,所以不用指定password什么的了 */

SSLContext sslc = SSLContext.getInstance("TLSv1");/*

* 获得TLSv1版本号的SSLContext,

* 还有个ssl3的

*/

sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),

new SecureRandom());/* 用两个工厂来初始化SSLContext */

SSLServerSocketFactory sllFactory = sslc.getServerSocketFactory();/* 获得server端口工厂 */

SSLServerSocket serverSocket = (SSLServerSocket) sllFactory

.createServerSocket(9999);/* 创建serverSocket,在9999端口监听 */

/* 这句非常重要,是要开启客户端的安全证书验证滴 */

serverSocket.setNeedClientAuth(true);

System.out.println("server已经启动了........");

while (true) {

final Socket socket = serverSocket.accept();/*

* accept用来堵塞监听线程,訪问一个处理一个

*/

System.out.println("接收到" + socket.getRemoteSocketAddress() + "的请求");

new Thread(new MyThread(socket)).start();/* 创建新的线程用来处理接受到的socket */

}

}

static class MyThread implements Runnable {

private Socket socket;

public MyThread(Socket socket) {

super();

this.socket = socket;

}

public void run() {

/** 这里是对接受的请求的处理,没什么东西了。

*/

try {

System.out.println("server開始读取数据=====");

BufferedReader read = new BufferedReader(new InputStreamReader(

socket.getInputStream()));

PrintWriter out = new PrintWriter(socket.getOutputStream(),

true);

String message;

while (null != (message = read.readLine())) {

if (message.equals("end")) {

out.println("agree");

break;

} else {

System.out.println("结果" + message);

out.println("server收到消息");

}

}

System.out.println("server跳出循环");

Thread.sleep(10000);

out.close();

read.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

client:

package com.mpc.test.clazz;

import java.io.BufferedReader;

import java.io.FileInputStream;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.security.KeyStore;

import java.security.SecureRandom;

import javax.net.ssl.KeyManagerFactory;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLSocket;

import javax.net.ssl.SSLSocketFactory;

import javax.net.ssl.TrustManagerFactory;

public class SSLTestClient {

public static void main(String[] args) throws Exception {

/* 从这里開始======== */

String key = "d:/keys/trustm.jks";

String client = "d:/keys/client.jks";

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

keyStore.load(new FileInputStream(key), "123456".toCharArray());

KeyStore clientStore = KeyStore.getInstance(KeyStore.getDefaultType());

clientStore.load(new FileInputStream(client), "123456".toCharArray());

TrustManagerFactory tmf = TrustManagerFactory

.getInstance(TrustManagerFactory.getDefaultAlgorithm());

tmf.init(keyStore);

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory

.getDefaultAlgorithm());

kmf.init(clientStore, "123456".toCharArray());

SSLContext sslc = SSLContext.getInstance("TLSv1");

sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),

new SecureRandom());

/* 到这里结束======== */

/** 上面凝视包围的内容,和server端的一样。仅仅是这里变成了客户端要使用的秘钥,客户端要信任的证书 */

SSLSocketFactory sslSocketFactory = sslc.getSocketFactory();/* 获得socketFactory */

SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(

"127.0.0.1", 9999);/* 訪问本机的9999端口 */

socket.setKeepAlive(true);/*长连接···*/

/*以下都是消息的处理,没什么东西了*/

BufferedReader read = new BufferedReader(new InputStreamReader(

socket.getInputStream()));

PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

out.println("cilent message");

String message;

int i = 0;

while (null != (message = read.readLine())) {

System.out.println(message);

i++;

if (message.equals("agree")) {

break;

} else {

}

Thread.sleep(1000);

out.println("cilent message");

if (i == 5) {

out.println("end");

}

}

socket.close();

out.close();

read.close();

System.out.println("客户端跳出了while循环");

}

}

測试结果:

1.server端:

dd00cf1e9f5d5f40c1ace53b35cb473d.png

2.client:

2663d74385e665eeb163d1bfabf11c39.png

在项目中使用到的证书

5eef43afea226de689de0ca10b0f9d5d.png

关于证书的创建。这里以server端的秘钥的创建和server要给client使用的信任证书的创建为例:

使用jdk自带的keytool来创建。

D:\keys>keytool -genkeypair -alias mkey -keyalg RSA -validity 7 -keystore m.jks

输入密钥库口令:

再次输入新口令:

您的名字与姓氏是什么?

[Unknown]: mi

您的组织单位名称是什么?

[Unknown]: my

您的组织名称是什么?

[Unknown]: isis

您所在的城市或区域名称是什么?

[Unknown]: city

您所在的省/市/自治区名称是什么?

[Unknown]: state

该单位的双字母国家/地区代码是什么?

[Unknown]: china

CN=mi, OU=my, O=isis, L=city, ST=state, C=china是否正确?

[否]: y

输入 的密钥口令

(假设和密钥库口令同样, 按回车):

再次输入新口令:

使用第一行的命令来生成证书。指定名字为m.jks。然后依据提示就能够创建server端的秘钥了。

D:\keys>keytool -export -alias mkey -keystore m.jks -rfc -file rootca.cer

输入密钥库口令:

存储在文件 中的证书

这条命令导出了server端的证书文件,用来供其它client验证server。可是java貌似不用这个,所以在把它导成jks的。

D:\keys>keytool -import -alias mcer -file rootca.cer -keystore trustm.jks

输入密钥库口令:

再次输入新口令:

全部者: CN=mi, OU=my, O=isis, L=city, ST=state, C=china

公布者: CN=mi, OU=my, O=isis, L=city, ST=state, C=china

序列号: 2ed10bf7

有效期開始日期: Wed Jan 27 16:24:15 CST 2016, 截止日期: Wed Feb 03 16:24:15 CST

2016

证书指纹:

MD5: 44:3A:CB:4D:B3:BE:FF:63:67:61:0C:19:97:DA:02:09

SHA1: 5E:D2:48:8F:37:29:00:94:99:AB:A1:93:B0:1F:2E:65:74:39:06:50

SHA256: 98:B3:62:6F:3A:77:F5:9E:BA:29:A8:55:16:E7:47:92:79:ED:45:26:E9:

7F:A8:ED:88:82:89:AA:FD:4C:3A:35

签名算法名称: SHA256withRSA

版本号: 3

扩展:

#1: ObjectId: 2.5.29.14 Criticality=false

SubjectKeyIdentifier [

KeyIdentifier [

0000: B0 51 15 9A E5 2F 8A 29 D2 4E 15 AE 0B 86 83 13 .Q.../.).N......

0010: EE BC 7B E2 ....

]

]

是否信任此证书?

[否]: y

证书已加入到密钥库中

这条命令就把server端给client验证的证书的jks文件生成了。

client的相关秘钥,证书的生成也是一样的。

本人才疏学浅,仅仅是想折腾折腾。学习学习,假设有什么不正确的,不足的地方,还请大家包涵。不吝赐教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值