您的位置:首页 > 编程语言 > Java开发

java实现SSL双向认证

2012-03-17 14:34 337 查看
 
原文链接:http://blog.163.com/khan7923@126/blog/static/7478696420109284182147/
 
 
实现技术:

JSSE(Java Security Socket Extension

是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)根据私钥,导出服务端证书



3)将服务端证书,导入到客户端的Trust KeyStore中



采用同样的方法,生成客户端的私钥,客户端的证书,并且导入到服务端的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 clientkey -file client.crt -keystore tserver.keystore



Server
Java代码

package ssl;   

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       = "123456";  

    private static final String SERVER_TRUST_KEY_STORE_PASSWORD = "123456";  

 

    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/ssl/kserver.keystore"), SERVER_KEY_STORE_PASSWORD.toCharArray());  

            tks.load(new FileInputStream("src/ssl/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 stub  

        start();  

    }  



package ssl;

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       = "123456";
    private static final String SERVER_TRUST_KEY_STORE_PASSWORD = "123456";

    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/ssl/kserver.keystore"), SERVER_KEY_STORE_PASSWORD.toCharArray());
            tks.load(new FileInputStream("src/ssl/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 stub
  start();
}
}

Client:
Java代码

package ssl;  

 

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       = "123456";  

    private static final String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456";  

 

    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 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/ssl/kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray());  

            tks.load(new FileInputStream("src/ssl/tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());  

 

            kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());  

            tmf.init(tks);  

 

            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);  

 

            sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT);  

        } catch (Exception e) {  

            System.out.println(e);  

        }  

    }  

 


package ssl;

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       = "123456";
    private static final String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456";

    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 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/ssl/kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray());
            tks.load(new FileInputStream("src/ssl/tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());

            kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());
            tmf.init(tks);

            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

            sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

}

启动Server
启动Client,发送信息。
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,进行逻辑处理。

如果过程中,解密失败,那么证明消息来源错误。不进行逻辑处理。这样就完成了双向的身份
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息