實現java ssl 雙向認證

 實現技術:
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文件中
2010年10月28日
 2)根據私鑰,導出服務端證書
2010年10月28日
 
3)將服務端證書,導入到客戶端的Trust KeyStore中
2010年10月28日
 
採用同樣的方法,生成客戶端的私鑰,客戶端的證書,並且導入到服務端的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
2010年10月28日
 
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接收如下:正確解密
2010年10月28日
 
 返回Client信息,如下:
2010年10月28日
  如此,就完成了服務端和客戶端之間的基於身份認證的交互。
client採用kclient.keystore中的clientkey私鑰進行數據加密,發送給server。
server採用tserver.keystore中的client.crt證書(包含了clientkey的公鑰)對數據解密,如果解密成功,證明消息來自client,進行邏輯處理。
server採用kserver.keystore中的serverkey私鑰進行數據加密,發送給client。
client採用tclient.keystore中的server.crt證書(包含了serverkey的公鑰)對數據解密,如果解密成功,證明消息來自server,進行邏輯處理。
如果過程中,解密失敗,那麼證明消息來源錯誤。不進行邏輯處理。這樣就完成了雙向的身份認證。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章