JAVA中SSL证书认证通讯

JAVA中SSL证书认证通讯

SSL通讯服务端

 /********************************************************************
 * 项目名称    :rochoc   <p>
 * 包名称      :rochoc.net.security <p>
 * 文件名称    :SSLServer   <p>
 * 编写者     :luoc    <p>
 * 编写日期    :2005-6-30    <p>
 * 程序功能(类)描述 :用于安全通讯的服务Socket,采用java中的SSLServerSocket<p>
 * 
 * 程序变更日期   :
 * 变更作者    :
 * 变更说明    :
********************************************************************/
package rochoc.net.security;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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.TrustManagerFactory;

/**
 * 类名:SSLServer  <p>
 * 类描述:安全通讯的服务端 <p>
 * 编写者 :luoc<p>
 * 编写日期 :2005-6-30<p>
 * 主要public成员变量:<p>
 * 主要public方法:   <p>
 **/

public class SSLServer implements Runnable
{
    /**
     *构造函数说明:       <p>
     *参数说明:   <p>
    **/
    public SSLServer()
    {        
        init();
    }
    
    /**
    * 方法名称:init<p>
    * 方法功能:初始化服务Socket            <p>
    * 参数说明: <p>
    * 返回:void <p>
    * 作者:luoc
    * 日期:2005-6-30
    **/
    public void init()
    {
        String type="TLS";//类型
        String keyf="..\key\srvstore";//key文件路径
        String trustf="..\key\mytrust";
        String pass="123456";//密码
        int port=2001;//端口
        try
        {
            //初始化上下文
            SSLContext ctx=SSLContext.getInstance(type);
            KeyManagerFactory kmf=KeyManagerFactory.getInstance("SunX509");
            TrustManagerFactory tmf=TrustManagerFactory.getInstance("SunX509");            
            KeyStore ks=KeyStore.getInstance("JKS");
            KeyStore tks=KeyStore.getInstance("JKS");
            //载入keystore
            ks.load(new FileInputStream(keyf),pass.toCharArray());
            tks.load(new FileInputStream(trustf),pass.toCharArray());
            kmf.init(ks,pass.toCharArray());
            tmf.init(tks);
            ctx.init(kmf.getKeyManagers(),tmf.getTrustManagers(),new SecureRandom());
            ss=(SSLServerSocket)ctx.getServerSocketFactory().createServerSocket(port);
            ss.setNeedClientAuth(true);//客户端要认证
        }catch (Exception e) {
      e.printStackTrace();
     }        
    }
    
    /**
    * 方法名称:newListener<p>
    * 方法功能:创建服务器监听            <p>
    * 参数说明: <p>
    * 返回:void <p>
    * 作者:luoc
    * 日期:2005-6-30
    **/
    private void newListener()
    {
        (new Thread(this)).start();
    }
    
    /**
     * 重载方法:run 处理客户端的请求<p>
     * 参阅:@see java.lang.Runnable#run() <p>
     * 参数说明: <p>
    **/
    public void run()
    {
        Socket socket=null;
        //accept a connection
        try
        {
            socket=ss.accept();
        }catch(IOException e)
        {
            System.out.println("Class Server died: " + e.getMessage());
         e.printStackTrace();
         return;
        }
        
        //create a new thread to accept the next connection
        newListener();
        
        //process connection
        try
        {
            OutputStream out=socket.getOutputStream();
            InputStream in=socket.getInputStream();
            //read data from client     
            byte buff[]=new byte [512];  
            byte data[]=new byte [1024];
            System.out.println("buff len="+buff.length);
            int len=0;
            int startpos=0;
            while((len=in.read(buff))!=-1)
            {
                //读联欢数据                
                if(len==1 && buff[0]==TranTool.DATA_END)//数据结束标志
                    break;
                data=TranTool.byteDynExt(data,buff,len,startpos);
                System.out.println("read len:"+len+" data:["+new String(buff,0,len)+"]");
                startpos+=len;
            }               
            System.out.println("recv from client:[");                                   
            System.out.print(new String(data,0,startpos));            
            System.out.println("] data end.");
            //send message to client
            out.write((startpos+" data success receive.").getBytes());
            out.write(TranTool.DATA_END);
            System.out.println("success echo is send.");
            out.flush();
        }catch(IOException e)
        {
            e.printStackTrace();
      return;
        }finally
        {
            try 
            {
          socket.close();
         } catch (IOException e) 
         {}
        }
    }    
    
    /*全局变量*/   
    SSLServerSocket ss=null;
    
    //测试函数
    public static void main(String args[])
    {
        System.out.println("init SSLServer...");
        SSLServer srv=new SSLServer();
        new Thread(srv).start();       
        System.out.println("SSLServer listener begin.");
    }
}

SSL通讯客户

/********************************************************************
 * 项目名称    :rochoc   <p>
 * 包名称      :rochoc.net.security <p>
 * 文件名称    :SSLClient   <p>
 * 编写者     :luoc    <p>
 * 编写日期    :2005-6-30    <p>
 * 程序功能(类)描述 :安全通讯的客户端       <p>
 * 
 * 程序变更日期   :
 * 变更作者    :
 * 变更说明    :
********************************************************************/
package rochoc.net.security;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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;

/**
 * 类名:SSLClient  <p>
 * 类描述: 安全通讯的客户端<p>
 * 编写者 :luoc<p>
 * 编写日期 :2005-6-30<p>
 * 主要public成员变量:<p>
 * 主要public方法:   <p>
 **/

public class SSLClient
{
    /**
     *构造函数说明:       <p>
     *参数说明:   <p>
    **/
    public SSLClient()
    {
        init();
    }
    
    /**
    * 方法名称:init<p>
    * 方法功能:初始化客户端Socket            <p>
    * 参数说明: <p>
    * 返回:void <p>
    * 作者:luoc
    * 日期:2005-6-30
    **/
    public void init()
    {
        //server socket's ip and port
        String host="localhost";
        int port=2001;
        //keystore path and password
        String keyf="..\key\mystore";
        String trustf="..\key\srvtrust";
        String pass="123456";
        //set up a connection
        SSLSocketFactory ssf=null;
        try
        {
            //init context
            SSLContext ctx=SSLContext.getInstance("TLS");            
            KeyManagerFactory kmf=KeyManagerFactory.getInstance("SunX509");
            TrustManagerFactory tmf=TrustManagerFactory.getInstance("SunX509");            
            KeyStore ks=KeyStore.getInstance("JKS");
            KeyStore tks=KeyStore.getInstance("JKS");
            //load keystore
            ks.load(new FileInputStream(keyf),pass.toCharArray());
            tks.load(new FileInputStream(trustf),pass.toCharArray());
            kmf.init(ks,pass.toCharArray());
            tmf.init(tks);
            ctx.init(kmf.getKeyManagers(),tmf.getTrustManagers(),new SecureRandom());
            System.out.println("load keystore success.");
            ssf=ctx.getSocketFactory();
            //create socket
            socket=(SSLSocket)ssf.createSocket(host,port);
            System.out.println("create socket success.");
            //handshake
            socket.startHandshake();
            System.out.println("handshake success.");
        }catch(Exception e)
        {
            System.out.println("establish connection error.");
            e.printStackTrace();
            return;
        }
        
    }
    
    /**
    * 方法名称:sendMessage<p>
    * 方法功能:发送信息            <p>
    * 参数说明:@param msg <p>
    * 返回:void <p>
    * 作者:luoc
    * 日期:2005-6-30
    **/
    public void sendMessage(String msg)
    {
        try
        {
            OutputStream out=socket.getOutputStream();
            InputStream in=socket.getInputStream();
            //send message
            System.out.println("send message:["+msg+"]");
            out.write(msg.getBytes());
            out.write(TranTool.DATA_END);
            out.flush();
            //receive message
            byte [] buff=new byte[1024];
            int len=0;
            System.out.println("recv len:"+(len=in.read(buff)));
            System.out.println("receive from srv:[");            
            System.out.print(new String(buff,0,len));            
            System.out.println("] receive end.");
        }catch(IOException e)
        {
            e.printStackTrace();
        }finally
        {
            try
            {
                socket.close();
            }catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    /*全局变量*/
    SSLSocket socket=null;
    
    //测试函数
    public static void main(String args[])
    {
        SSLClient sc=new SSLClient();
        String msg="Hello SSL Server.";
        if(args.length==1)
        {
            msg=args[0];
        }else
        {
            System.out.println("Useage:Please input the message you want to send.");
        }
        sc.sendMessage(msg);
    }
}

安全认证证书的生成

需要两套证书:

 1、客户端(公钥、私钥) 2、服务端(公钥、私钥)

    服务端应用‘服务端私钥’和‘客户端公钥’与客户端通讯;客户端应用‘客户端私钥’和‘服务端公钥’与服务端通讯。

 如下介绍证书生成(一套):

 1、用JDK的keytool生成密钥store

    keytool -genkey -alias mykey -keystore srvstore

    输入密码(程序中密码为‘123456’)和相应的证书信息

    2、从srvstore中导出证书

    keytool -export -alias mykey -file srvcert.crt -keystore srvstore

    输入刚才上面设置的密码

    3、将证书导到公钥中

     keytool -import -alias mytrust -file srvcert.crt -keystore srvtrust

     输入公钥的密码(程序中密码为‘123456’)

     另一套证书的生成同上

原文地址:https://www.cnblogs.com/xunbu7/p/4254100.html