前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >国密SSL协议之Java编程

国密SSL协议之Java编程

原创
作者头像
gmssl
修改2020-08-25 14:48:08
3.1K0
修改2020-08-25 14:48:08
举报

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("\r\naddr="+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("\r\nGM 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.1\r\n";
   s+= "Accept: */*\r\n";
   s+= "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)\r\n";
   s+= "Host: " + addr + (port == 443 ? "" : ":"+port) + "\r\n";
   s+= "Connection: Close\r\n";
   s+= "\r\n";
   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,可供学习和测试。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 背景
  • 2 环境
  • 3 源码
  • 4 注释
  • 5 测试运行
  • 6 小结
相关产品与服务
网站建设
网站建设(Website Design Service,WDS),是帮助您快速搭建企业网站的服务。通过自助模板建站工具及专业设计服务,无需了解代码技术,即可自由拖拽模块,可视化完成网站管理。全功能管理后台操作方便,一次更新,数据多端同步,省时省心。使用网站建设服务,您无需维持技术和设计师团队,即可快速实现网站上线,达到企业数字化转型的目的。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档