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’)
另一套证书的生成同上