Java安全套接字编程-通过SSLContext指定证书库和信任库

客户端和服务器端证书的生成,请看:

http://my.oschina.net/xinxingegeya/blog/266826

http://www.ibm.com/developerworks/cn/java/j-lo-socketkeytool/

参考文章:http://www.ibm.com/developerworks/cn/java/j-lo-socketkeytool/

参考文章:http://willtea.iteye.com/blog/1841281


本篇主要关于SSLContext,及其设置证书库和信任库

SSLContext 指定证书库

 // 相关的 jks 文件及其密码定义
 private final static String CERT_STORE="D:/test_server_cert.jks"; 
 private final static String CERT_STORE_PASSWORD="Testpassw0rd";
 // 载入 jks 文件
 FileInputStream f_certStore=new FileInputStream(CERT_STORE); 
 KeyStore ks=KeyStore.getInstance("jks"); 
 ks.load(f_certStore, CERT_STORE_PASSWORD.toCharArray()); 
 f_certStore.close(); 
 // 创建并初始化证书库工厂
 String alg=KeyManagerFactory.getDefaultAlgorithm(); 
 KeyManagerFactory kmFact=KeyManagerFactory.getInstance(alg); 
 kmFact.init(ks, CERT_STORE_PASSWORD.toCharArray()); 
 KeyManager[] kms=kmFact.getKeyManagers(); 
 // 创建并初始化 SSLContext 实例
 SSLContext context=SSLContext.getInstance("SSL"); 
 context.init(kms, null, null); 
 SSLServerSocketFactory ssf=(SSLServerSocketFactory)context.getServerSocketFactory();

SSLContext 指定信任库

// 相关的 jks 文件及其密码定义
 private final static String TRUST_STORE="D:/test_client_trust.jks"; 
 private final static String TRUST_STORE_PASSWORD="Testpassw0rd";
// 载入 jks 文件
 FileInputStream f_trustStore=new FileInputStream(TRUST_STORE); 
 KeyStore ks=KeyStore.getInstance("jks"); 
 ks.load(f_trustStore, TRUST_STORE_PASSWORD.toCharArray()); 
 f_trustStore.close(); 
 // 创建并初始化信任库工厂
 String alg=TrustManagerFactory.getDefaultAlgorithm(); 
 TrustManagerFactory tmFact=TrustManagerFactory.getInstance(alg); 
 tmFact.init(ks); 
 TrustManager[] tms=tmFact.getTrustManagers(); 
 // 创建并初始化 SSLContext 实例
 SSLContext context=SSLContext.getInstance("SSL"); 
 context.init(null, tms, null); 
 SSLSocketFactory sf=context.getSocketFactory();

当然,如果要在服务端或者客户端同时使用证书库和信任库,可将清单 3 和清单 4 的代码用在同一处 context.init() 的地方。

这里需要说明的是,如果 context.init() 的第一个 KeyManager[] 参数为 null,则表示不提供证书;如果第二个 TrustManager[] 参数为 null,则会寻找系统默认提供的信任库 ( 例如:JRE 安装目录下的 lib/security/cacerts)。


服务器端程序

package ssl4;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyStore;

import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.TrustManagerFactory;

public class SSLServer extends Thread {
    private Socket socket;

    public SSLServer(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter writer = new PrintWriter(socket.getOutputStream());

            String data = reader.readLine();
            writer.println(data);
            writer.close();
            socket.close();
        } catch (IOException e) {
        }
    }

    private static String SERVER_KEY_STORE = "E:\\javassl2\\sslserverkeys";
    private static String SERVER_TRUST_KEY_STORE = "E:\\javassl2\\sslservertrust";
    private static String SERVER_KEY_STORE_PASSWORD = "123456";
    private static String SERVER_TRUST_KEY_STORE_PASSWORD = "123456";

    public static void main(String[] args) throws Exception {

        //加载证书库
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(new FileInputStream(SERVER_KEY_STORE), SERVER_KEY_STORE_PASSWORD.toCharArray());

        //加载信任库
        KeyStore trustKs = KeyStore.getInstance("JKS");
        trustKs.load(new FileInputStream(SERVER_TRUST_KEY_STORE), SERVER_TRUST_KEY_STORE_PASSWORD.toCharArray());

        //创建并初始化证书库工厂
        String alg = KeyManagerFactory.getDefaultAlgorithm();
//        KeyManagerFactory kf = KeyManagerFactory.getInstance("SunX509");
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(alg);
        kmf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray());

        // 创建并初始化信任库工厂
        String alg_trust = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(alg_trust);
        tmf.init(trustKs);

        SSLContext context = SSLContext.getInstance("TLS");
        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        /**
         * 通过SSLContext得到serverSocketFactory
         */
        ServerSocketFactory factory = context.getServerSocketFactory();
        ServerSocket _socket = factory.createServerSocket(8443);
        ((SSLServerSocket) _socket).setNeedClientAuth(true);
        while (true) {
            new SSLServer(_socket.accept()).start();
        }
    }
}

客户端程序

package ssl4;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.security.KeyStore;
import javax.net.SocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

public class SSLClient {
    private static String CLIENT_KEY_STORE = "E:\\javassl2\\sslclientkeys";
    private static String CLIENT_TRUST_KEY_STORE = "E:\\javassl2\\sslclienttrust";
    private static String CLIENT_KEY_STORE_PASSWORD = "123456";
    private static String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456";


    public static void main(String[] args) throws Exception {

        SSLClient client = new SSLClient();
        Socket s = client.clientWithCert();

        PrintWriter writer = new PrintWriter(s.getOutputStream());
        BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
        writer.println("hello");
        writer.flush();
        System.out.println(reader.readLine());
        s.close();
    }

    private Socket clientWithoutCert() throws Exception {
        SocketFactory sf = SSLSocketFactory.getDefault();
        Socket s = sf.createSocket("localhost", 8443);
        return s;
    }

    private Socket clientWithCert() throws Exception {

        //加载证书库
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(new FileInputStream(CLIENT_KEY_STORE), CLIENT_KEY_STORE_PASSWORD.toCharArray());
        //加载信任库
        KeyStore trustKs = KeyStore.getInstance("JKS");
        trustKs.load(new FileInputStream(CLIENT_TRUST_KEY_STORE), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());

        //创建并初始化证书库工厂
        String alg = KeyManagerFactory.getDefaultAlgorithm();
//        KeyManagerFactory kf = KeyManagerFactory.getInstance("SunX509");
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(alg);
        kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());

        // 创建并初始化信任库工厂
        String alg_trust = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(alg_trust);
        tmf.init(trustKs);


        /**
         * TLS安全套接字
         * Returns a SSLContext object that implements the specified secure socket protocol.
         */
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        SocketFactory factory = context.getSocketFactory();
        Socket s = factory.createSocket("localhost", 8443);
        return s;
    }
}



你可能感兴趣的:(Java安全套接字编程-通过SSLContext指定证书库和信任库)