国密SSL协议之Java编程
时间:2022-07-23
本文章向大家介绍国密SSL协议之Java编程,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
1 背景
Java自身通过JCE和JSSE支持标准的SSL协议,但并不支持国密SSL协议。本文描述了Java使用国密JCE和国密JSSE开发一个简单的客户端程序,连接国密Web网站,发送HTTP请求,并接收HTTP应答。
2 环境
JRE是jre8。
国密JCE和国密JSSE。下载参https://www.gmssl.cn/gmssl/index.jsp?go=gmsdk
gmjce.jar和gmjsse.jar放到jre的lib/ext/目录下
3 源码
package cn.gmssl.test;
import java.net.*;
import java.io.*;
import java.security.*;
import java.security.cert.*;
import javax.net.*;
import javax.net.ssl.*;
public class SocketGet
{
public static void main(String[] args)
{
SocketFactory fact = null;
SSLSocket socket = null;
String addr = "ebssec.boc.cn";
int port = 443;
String uri = "/";
try
{
if(args.length > 0)
{
addr = args[0];
port = Integer.parseInt(args[1]);
uri = args[2];
}
System.out.println("rnaddr="+addr);
System.out.println("port="+port);
System.out.println("uri="+uri);
// 加载国密提供者
Security.insertProviderAt(new cn.gmssl.jce.provider.GMJCE(), 1);
Security.insertProviderAt(new cn.gmssl.jsse.provider.GMJSSE(), 2);
fact = createSocketFactory(null, null);
socket = (SSLSocket)fact.createSocket();
socket.setTcpNoDelay(true);
System.out.println("rnGM SSL connecting...");
socket.connect(new InetSocketAddress(addr, port), 5000);
socket.setTcpNoDelay(true);
socket.startHandshake();
System.out.println("Connected!n");
DataInputStream in = new DataInputStream(socket.getInputStream());
OutputStream out = socket.getOutputStream();
String s = "GET " + uri + " HTTP/1.1rn";
s+= "Accept: */*rn";
s+= "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)rn";
s+= "Host: " + addr + (port == 443 ? "" : ":"+port) + "rn";
s+= "Connection: Closern";
s+= "rn";
out.write(s.getBytes());
out.flush();
// 读取HTTP头
while(true)
{
byte[] lineBuffer = ReadLine.read(in);
if ( lineBuffer == null || lineBuffer.length == 0)
{
System.out.println();
break;
}
String line = new String(lineBuffer);
System.out.println(line);
}
// 读取HTTP内容
{
byte[] buf = new byte[1024];
while(true)
{
int len = in.read(buf);
if(len == -1)
{
break;
}
System.out.println(new String(buf, 0, len));
}
}
in.close();
out.close();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
socket.close();
}
catch(Exception e)
{}
}
}
private static SSLSocketFactory createSocketFactory(KeyStore kepair, char[] pwd) throws Exception
{
X509TrustManager[] trust = { new MyTrustAllManager() };
KeyManager[] kms = null;
if (kepair != null)
{
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(kepair, pwd);
kms = kmf.getKeyManagers();
}
// 使用国密SSL
String protocol = cn.gmssl.jsse.provider.GMJSSE.GMSSLv11;
String provider = cn.gmssl.jsse.provider.GMJSSE.NAME;
SSLContext ctx = SSLContext.getInstance(protocol, provider);
java.security.SecureRandom secureRandom = new java.security.SecureRandom();
ctx.init(kms, trust, secureRandom);
SSLSocketFactory factory = ctx.getSocketFactory();
return factory;
}
}
class MyTrustAllManager implements X509TrustManager
{
private X509Certificate[] issuers;
public MyTrustAllManager()
{
this.issuers = new X509Certificate[0];
}
public X509Certificate[] getAcceptedIssuers()
{
return issuers ;
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
{}
public void checkServerTrusted(X509Certificate[] chain, String authType)
{}
}
class ReadLine
{
public static final byte[] CRLF = {'r', 'n'};
public static final byte CR = 'r';
public static final byte LF = 'n';
private static final int LINE_MAX_SIZE = 16384;
public static byte[] read(DataInputStream in) throws IOException, SocketException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream s = new DataOutputStream(baos);
boolean previousIsCR = false;
int len = 0;
byte b = 0;
try
{
b = in.readByte();
len ++;
}
catch(EOFException e)
{
return new byte[0];
}
while(true)
{
if(b == LF)
{
if(previousIsCR)
{
s.flush();
byte[] rs = baos.toByteArray();
s.close();
return rs;
}
else
{
s.flush();
byte[] rs = baos.toByteArray();
s.close();
return rs;
}
}
else if(b == CR)
{
if(previousIsCR)
{
s.writeByte(CR);
}
previousIsCR = true;
}
else
{
if(previousIsCR)
{
s.writeByte(CR);
}
previousIsCR = false;
s.write(b);
}
if(len > LINE_MAX_SIZE)
{
s.close();
throw new IOException("Reach line size limit");
}
try
{
b = in.readByte();
len ++;
}
catch(EOFException e)
{
s.flush();
byte[] rs = baos.toByteArray();
s.close();
return rs;
}
}
}
}
4 注释
首先要注册国密提供者
Security.insertProviderAt(new cn.gmssl.jce.provider.GMJCE(), 1);
Security.insertProviderAt(new cn.gmssl.jsse.provider.GMJSSE(), 2);
其中要使用国密SSL来连接
String protocol = cn.gmssl.jsse.provider.GMJSSE.GMSSLv11;
String provider = cn.gmssl.jsse.provider.GMJSSE.NAME;
SSLContext ctx = SSLContext.getInstance(protocol, provider);
是不是比想象中要简单?
5 测试运行
java cn.gmssl.test.SocketGet
addr=ebssec.boc.cn
port=443
uri=/
GM SSL connecting...
Connected!
HTTP/1.1 200 OK
Date: Mon, 24 Aug 2020 03:45:28 GMT
Last-Modified: Sat, 27 Jun 2015 16:48:38 GMT
Accept-Ranges: bytes
Content-Length: 156
Cache-Control: max-age=300
Expires: Mon, 24 Aug 2020 03:50:28 GMT
Vary: Accept-Encoding,User-Agent
Connection: close
Content-Type: text/html
<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0;url=/boc15/login.html"><meta name="renderer" content="ie-stand"></head><body></body></html>
6 小结
通过使用国密JCE和国密JSSE,Java很容易编程来使用国密SSL连接国密Web网站。gmssl.cn提供了全部免费的测试组件,并且支持双向国密SSL,可供学习和测试。
- 关于虚拟索引的学习(r3笔记第75天)
- python数据挖掘:能不能找出吃货最佳住宿点?
- 解决ajax跨域请求 (总结)
- Python+Selenium+PIL+Tesseract真正自动识别验证码进行一键登录
- 在深度学习TensorFlow 框架上使用 LSTM 进行情感分析
- python玩微信:如何获得自己微信的好友统计信息
- 关于不可见索引的学习(r3笔记74天)
- 【专业技术第五讲】动态链接库及其用法
- 用scrapy爬虫抓取慕课网课程数据详细步骤
- 关于pl/sql中的绑定变量(r3笔记第73天)
- python爬取网易云音乐并分析:用户有什么样的音乐偏好?
- shell基础学习总结(二) (r3笔记第72天)
- 对IMP-00013问题的思考(r3笔记第71天)
- 搭建LSTM(深度学习模型)做文本情感分类的代码
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- java编程思想第四版第八章习题
- java编程思想第四版第八章总结
- ESP32从网络获取天气OLED显示(附源码)
- 02 . Zabbix配置监控项及聚合图形
- 01 . GitLab简介及环境部署
- 03 . Prometheus监控容器和HTTP探针应用及服务发现
- java编程思想第四版第九章习题
- 03 . Django之腾讯云短信
- ESP32 MQTT连接到中移OneNET物联网平台(附源码)
- 01 . Docker原理部署及常用操作命令
- SSH原理常见应用升级及端口转发
- 01 . Linux常用命令
- 私人订制属于自己的Linux系统
- 04 . Docker安全与Docker底层实现
- 03 . Docker数据资源管理与网络