java实现SSL双向认证

本文详细介绍了如何使用JSSE实现SSL安全通信,包括证书的生成、验证过程及Java代码实现,确保了客户端与服务器间的数据传输安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

原文链接: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接收如下:正确解密

2010年10月28日 - khan7923@126 - 漫漫浪漫

返回Client信息,如下:

2010年10月28日 - khan7923@126 - 漫漫浪漫

  如此,就完成了服务端和客户端之间的基于身份认证的交互。
client采用kclient.keystore中的clientkey私钥进行数据加密,发送给server。
server采用tserver.keystore中的client.crt证书(包含了clientkey的公钥)对数据解密,如果解密成功,证明消息来自client,进行逻辑处理。
server采用kserver.keystore中的serverkey私钥进行数据加密,发送给client。
client采用tclient.keystore中的server.crt证书(包含了serverkey的公钥)对数据解密,如果解密成功,证明消息来自server,进行逻辑处理。
如果过程中,解密失败,那么证明消息来源错误。不进行逻辑处理。这样就完成了双向的身份

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值