使用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());

 

posted @ 2020-04-23 18:33  DurianTRY  阅读(3259)  评论(0编辑  收藏  举报