使用SSLSocket实现双向认证(keytool证书创建双向认证证书(这里有根证书)的详细步骤以及踩雷)
一、SSL的双向认证步骤以及Keytool的使用方法
就不再多说,网上一搜一大堆
二、Keytool创建双向认证证书步骤
由于收费的CA证书搞不到,平常也用不到,这里只使用了自签名证书。
- 创建根证书
这里直接回车即可。
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());
由于无法解释的神圣旨意,我们徒然地到处找你;你就是孤独,你就是神秘,比恒河或者日落还要遥远。。。。。。