使用SSLSocket實現雙向認證(keytool證書創建雙向認證證書(這裡有根證書)的詳細步驟以及踩雷)

一、SSL的雙向認證步驟以及Keytool的使用方法

  就不再多說,網上一搜一大堆

二、Keytool創建雙向認證證書步驟

  由於收費的CA證書搞不到,平常也用不到,這裡只使用了自簽名證書。

  1. 創建根證書

這裡直接回車即可。

  2.創建客戶端證書以及服務端證書

服務端

  3.導出客戶端以及服務端證書認證請求

服務端

  4.使用根證書認證客戶端以及服務端證書,並生成證書

服務端

  5.將根證書導入客戶端以及服務端密鑰庫,再將認證後的證書分別導入密鑰庫。

  此時應先將根證書導入客戶端以及服務端密鑰庫中,不然會報錯,這裡只演示客戶端

三、客戶端以及服務端的身份認證過程代碼

// key store相關信息  
            String keyStoreName = "client.keystore";  
            char[] keyStorePwd = "clientstorepass".toCharArray();  
            char[] keyPwd = keyStorePwd;  
            
            KeyStore keyStore = KeyStore.getInstance("JKS");
            KeyStore trustKeyStore = KeyStore.getInstance("JKS");
            keyStore.load(new FileInputStream("D:\\eclipsefiles\\cert\\"+keyStoreName),keyStorePwd);//必須先加載 keystore 才能對其進行訪問
            trustKeyStore.load(new FileInputStream("D:\\eclipsefiles\\cert\\server\\server.keystore"),"serverstorepass".toCharArray());
            //創建管理JKS密鑰庫的X.509密鑰管理器
            KeyManagerFactory kmf=KeyManagerFactory.getInstance("SunX509");
            kmf.init(keyStore,keyPwd);//使用密鑰內容源初始化此工廠。    提供者通常使用 KeyStore 來獲取在安全套接字協商期間所使用的密鑰內容
            
            TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509");
            tmFactory.init(trustKeyStore);
            
            //初始sslcontext
//            SSLContext sslContext=SSLContext.getInstance("SSLv3");
            SSLContext sslContext=SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(),tmFactory.getTrustManagers(),new SecureRandom()); ////trustmanager決定是否信任對方證書
            // 生成套接字
            SSLSocketFactory socketFactory = sslContext.getSocketFactory(); 
            
            socket = (SSLSocket) socketFactory.createSocket("127.0.0.1", 7070); //主機IP地址以及端口
            
            socket.setEnabledCipherSuites(socket.getSupportedCipherSuites());
            socket.setUseClientMode(true);//false設置處於服務器模式
            socket.setEnableSessionCreation( true );

這裡客戶端的受信任密鑰庫是直接使用的服務端的密鑰庫,也是可行的,但實際上還是應該重新建一個客戶端受信任密鑰庫,裏面導入服務端證書以及根證書,例如下面服務端的示例代碼

// key store相關信息  
        String keyStoreName = "server.keystore";  
        char[] keyStorePwd = "serverstorepass".toCharArray();  
        char[] keyPwd = keyStorePwd;  
        KeyStore keyStore = KeyStore.getInstance("JKS");
        KeyStore trustKeyStore = KeyStore.getInstance("JKS");
        keyStore.load(new FileInputStream("D:\\eclipsefiles\\cert\\server\\"+keyStoreName),keyStorePwd);//必須先加載 keystore 才能對其進行訪問
        trustKeyStore.load(new FileInputStream("D:\\eclipsefiles\\cert\\server\\trustserver.keystore"),"trustserverpass".toCharArray());
        
        //創建管理JKS密鑰庫的X.509密鑰管理器
        KeyManagerFactory kmf=KeyManagerFactory.getInstance("SunX509");
        kmf.init(keyStore,keyPwd);//使用密鑰內容源初始化此工廠。    提供者通常使用 KeyStore 來獲取在安全套接字協商期間所使用的密鑰內容
        KeyManager[] keyManagers=kmf.getKeyManagers();//Keymanager用於選擇自己的安全證書,並發送給對方
        
        TrustManagerFactory tmFactory=TrustManagerFactory.getInstance("SunX509");
        tmFactory.init(trustKeyStore);
        TrustManager[] tManagers=tmFactory.getTrustManagers();//trustmanager決定是否信任對方證書
        
        SSLContext sslContext=SSLContext.getInstance("TLS");
        sslContext.init(keyManagers,tManagers,new SecureRandom());
     
        //根據上面配置的SSL上下文來產生SSLServerSocketFactory,與通常的產生方法不同
        SSLServerSocketFactory factory=sslContext.getServerSocketFactory();

        serverSocket=(SSLServerSocket)factory.createServerSocket(7070);
        
        serverSocket.setUseClientMode(false);//設置處於服務器模式,需要向對方出具安全證書
        serverSocket.setNeedClientAuth(true);//設置需要對方的安全證書,否則連接中斷

        serverSocket.setEnabledCipherSuites(serverSocket.getEnabledCipherSuites());

 

Tags: