SSlSocket和SSLServerSocket的学习

来源:互联网 发布:淘宝如何延迟确认收货 编辑:程序博客网 时间:2024/05/22 12:58

什么是SSLSocket

JDK文档指出,SSLSocket扩展Socket并提供使用SSL或TLS协议的安全套接字。

这种套接字是正常的流套接字,但是它们在基础网络传输协议(如TCP)上添加了安全保护层。

具体安全方面的讨论见下一篇。本篇重点关注SSLSocket及相关几个类的使用。

 

 SSLSocket和相关类

SSLSocket来自jsse(Java Secure Socket Extension)。

 

 

(1)SSLContext: 此类的实例表示安全套接字协议的实现, 它是SSLSocketFactory、SSLServerSocketFactory和SSLEngine的工厂。

 

(2)SSLSocket: 扩展自Socket

 

(3)SSLServerSocket: 扩展自ServerSocket

 

(4)SSLSocketFactory: 抽象类,扩展自SocketFactory, SSLSocket的工厂

 

(5)SSLServerSocketFactory: 抽象类,扩展自ServerSocketFactory, SSLServerSocket的工厂

 

(6)KeyStore: 表示密钥和证书的存储设施

 

(7)KeyManager: 接口,JSSE密钥管理器

 

(8)TrustManager: 接口,信任管理器(?翻译得很拗口)

 

(9)X590TrustedManager: TrustManager的子接口,管理X509证书,验证远程安全套接字






实现技术:

JSSE(Java Security SocketExtension)

是Sun为了解决在Internet上的实现安全信息传输的解决方案。它实现了SSL和TSL(传输层安全)协议。在JSSE中包含了数据加密,服务器验证,消息完整性和客户端验证等技术。通过使用JSSE,可以在Client和Server之间通过TCP/IP协议安全地传输数据。

 

 

 为了实现消息认证。

Server需要:

1)KeyStore: 其中保存服务端的私钥

2)Trust KeyStore:其中保存客户端的授权证书

Client需要:

1)KeyStore:其中保存客户端的私钥

2)Trust KeyStore:其中保存服务端的授权证书

 

 

 使用Java自带的keytool命令,去生成这样信息文件:

 

1)  生成服务端私钥,并且导入到服务端KeyStore文件中:

 

2、根据私钥,导出服务器证书:keytool -export -alias serverkey -keystore kserver.keystore -file server.crt

 

3、将服务器证书,导入到客户端的Trust KeyStore中:keytool -import -alias serverkey -file server.crt -keystore tclient.store



 采用同样的方法,生成客户端的私钥,客户端的证书,并且导入到服务端的Trust KeyStore:

1、keytool -genkey -alias clientkey -keystore kclient.keystore

2、keytool export -alias clientkey -keystore kclient.keystore -file client.crt

3、keytool -import -alias client -file client.crt -keystore tserver.keystore


将生成的tclient.keystore、tserver.keystore、kclient.keystore、kserver.keystore导入要项目:




Server代码如下:

import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.security.KeyStore;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLServerSocket;import javax.net.ssl.TrustManagerFactory;/** * * @author Leo */public class Server implements Runnable{    private static final int    DEFAULT_PORT                    = 7777;    private static final String SERVER_KEY_STORE_PASSWORD       = "1234qwer?";    private static final String SERVER_TRUST_KEY_STORE_PASSWORD = "1234qwer?";    private SSLServerSocket     serverSocket;    /**     * 启动程序     *      * @param args     */    public static void main(String[] args) {        Server server = new Server();        server.init();Thread thread = new Thread(server);thread.start();    }    public synchronized void start() {        if (serverSocket == null) {            System.out.println("ERROR");            return;        }        while (true) {            try {                Socket s = serverSocket.accept();                InputStream input = s.getInputStream();                OutputStream output = s.getOutputStream();                BufferedInputStream bis = new BufferedInputStream(input);                BufferedOutputStream bos = new BufferedOutputStream(output);                byte[] buffer = new byte[20];                bis.read(buffer);                System.out.println("------receive:--------"+new String(buffer).toString());                bos.write("yes".getBytes());                bos.flush();                s.close();            } catch (Exception e) {                System.out.println(e);            }        }    }    public void init() {        try {            SSLContext ctx = SSLContext.getInstance("SSL");            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");            KeyStore ks = KeyStore.getInstance("JKS");            KeyStore tks = KeyStore.getInstance("JKS");            ks.load(new FileInputStream("src/kserver.keystore"), SERVER_KEY_STORE_PASSWORD.toCharArray());            tks.load(new FileInputStream("src/tserver.keystore"), SERVER_TRUST_KEY_STORE_PASSWORD.toCharArray());            kmf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray());            tmf.init(tks);            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);            serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(DEFAULT_PORT);            serverSocket.setNeedClientAuth(true);         } catch (Exception e) {            System.out.println(e);        }    }public void run() {// TODO Auto-generated method stubstart();}}

Client代码如下:
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.security.KeyStore;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocket;import javax.net.ssl.TrustManagerFactory;/** * SSL Client *  * @author Leo */public class Client {    private static final String DEFAULT_HOST                    = "127.0.0.1";    private static final int    DEFAULT_PORT                    = 7777;    private static final String CLIENT_KEY_STORE_PASSWORD       = "1234qwer?";    private static final String CLIENT_TRUST_KEY_STORE_PASSWORD = "1234qwer?";    private SSLSocket           sslSocket;    /**     * 启动客户端程序     *      * @param args     */    public static void main(String[] args) {       Client client = new Client();        client.init();        client.process();    }     public void process() {        if (sslSocket == null) {            System.out.println("ERROR");            return;        }        try {            InputStream input = sslSocket.getInputStream();            OutputStream output = sslSocket.getOutputStream();            BufferedInputStream bis = new BufferedInputStream(input);            BufferedOutputStream bos = new BufferedOutputStream(output);            bos.write("1234567890".getBytes());            bos.flush();            byte[] buffer = new byte[20];            bis.read(buffer);            System.out.println(new String(buffer));            sslSocket.close();        } catch (IOException e) {            System.out.println(e);        }    }    public void init() {        try {        //获取SSlContext对象            SSLContext ctx = SSLContext.getInstance("SSL");            //JSSE密钥管理器KeyManagerFactory对象            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");            //信任管理器TrustManagerFactory对象            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");            //密钥和证书的存储设施            KeyStore ks = KeyStore.getInstance("JKS");            KeyStore tks = KeyStore.getInstance("JKS");            //载入keystore            ks.load(new FileInputStream("src/kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray());            tks.load(new FileInputStream("src/tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());            //KeyManagerFactory对象初始化            kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());            //TrustManagerFactory对象初始化            tmf.init(tks);            //SSLContext对象初始化            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);            //创建连接sslSocket对象            sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT);        } catch (Exception e) {            System.out.println(e);        }    }}

 运行时,先启动server,在运行client,否则报错。


这样,就完成了服务端和客户端之间的基于身份认证的交互。


交互原理:

client采用kclient.keystore中的clientkey私钥进行数据加密,发送给server。

server采用tserver.keystore中的client.crt证书(包含了clientkey的公钥)对数据解密,如果解密成功,来自client,进行逻辑处理。

 

 

server采用kserver.keystore中的serverkey私钥进行数据加密,发送给client。

client采用tclient.keystore中的server.crt证书(包含了serverkey的公钥)对数据解密,如果解密成功,来自server,进行逻辑处理。


过程中,如果解密失败,证明消息来源错误,不进行逻辑处理。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 0