Java-JSSE-SSL/TLS编程代码实例-双向认证

浅谈SSL/TLS协议及其实现 开篇感谢大神们指引方向,参考资料: https://www.paolotagliaferri.com/an-overview-of-ssl-tls-secure-sockets-layer-transport-layer-security-tls-1-2/ https://www.paolotagliaferri.com/overview-of-transport-layer-security-protocol-tls-1-3/ https://tls13.ulfheim.net/ 《图解密码技术》 阅读详情

转:http://blog.youkuaiyun.com/fw0124/article/details/41013333


关于SSL/TLS/JSSE的介绍:
1)SSL/TLS协议运行机制
2)图解SSL/TLS协议
3)使用wireshark观察SSL/TLS握手过程
4)SSL/TLS的Java实现--JSSE

(一)使用keytool创建密钥库

使用双向认证的SSL/TLS协议通信,客户端和服务器端都要设置用于证实自己身份的安全证书,并且还要设置信任对方的哪些安全证书。
理论上一共需要准备四个文件,两个keystore文件和两个truststore文件。
通信双方分别拥有一个keystore和一个truststore,keystore用于存放自己的密钥和公钥,truststore用于存放所有需要信任方的公钥。

首先使用JDK自带的keytool工具来生成keystore和truststore。这里使用的Java版本是1.7。
1)创建server的keystore文件,生成server的公钥/私钥密钥对。需要指定keystore的密码(storepass)和密钥对的密码(keypass)。
访问keystore需要storepass。访问密钥对需要keypass。

  1. <span style="font-family:Verdana;">C:\Program Files\Java\jre7\bin>keytool -genkey -alias catserver -keyalg rsa -keysize 1024 -sigalg sha256withrsa -keypass catserver -keystore c:\_tmp\catserver.keystore -storepass catserverks  
  2. What is your first and last name?  
  3. [Unknown]: cat  
  4. What is the name of your organizational unit?  
  5. [Unknown]: cat  
  6. What is the name of your organization?  
  7. [Unknown]: cat  
  8. What is the name of your City or Locality?  
  9. [Unknown]: cat  
  10. What is the name of your State or Province?  
  11. [Unknown]: cat  
  12. What is the two-letter country code for this unit?  
  13. [Unknown]: ct  
  14. Is CN=cat, OU=cat, O=cat, L=cat, ST=cat, C=ct correct?  
  15. [no]: y</span>  


2)创建client的keystore文件。同样需要指定keystore的密码和密钥对的密码。

  1. <span style="font-family:Verdana;">C:\Program Files\Java\jre7\bin>keytool -genkey -alias foxclient -keyalg dsa -keysize 512 -sigalg sha1withdsa -keypass foxclient -keystore c:\_tmp\foxclient.keystore -storepass foxclientks  
  2. What is your first and last name?  
  3. [Unknown]: fox  
  4. What is the name of your organizational unit?  
  5. [Unknown]: fox  
  6. What is the name of your organization?  
  7. [Unknown]: fox  
  8. What is the name of your City or Locality?  
  9. [Unknown]: fox  
  10. What is the name of your State or Province?  
  11. [Unknown]: fox  
  12. What is the two-letter country code for this unit?  
  13. [Unknown]: fx  
  14. Is CN=fox, OU=fox, O=fox, L=fox, ST=fox, C=fx correct?  
  15. [no]: y</span>  


3)从server的keystore中导出server的证书(其中包括server的公钥)。

  1. <span style="font-family:Verdana;">C:\Program Files\Java\jre7\bin>keytool -export -alias catserver -keystore c:\_tmp\catserver.keystore -storepass catserverks -file c:\_tmp\catserver.cer  
  2. Certificate stored in file <c:\_tmp\catserver.cer>  
  3. </span>  

4)从client的keystore中导出client的证书(其中包括client的公钥)。

  1. <span style="font-family:Verdana;">C:\Program Files\Java\jre7\bin>keytool -export -alias foxclient -keystore c:\_tmp\foxclient.keystore -storepass foxclientks -file c:\_tmp\foxclient.cer  
  2. Certificate stored in file <c:\_tmp\foxclient.cer>  
  3. </span>  


5)创建server的truststore文件并导入client的证书(其中包括client的公钥)。

  1. <span style="font-family:Verdana;">C:\Program Files\Java\jre7\bin>keytool -import -alias foxclient -keystore c:\_tmp\catservertrust.keystore -storepass catservertrustks -file c:\_tmp\foxclient.cer  
  2. Owner: CN=fox, OU=fox, O=fox, L=fox, ST=fox, C=fx  
  3. Issuer: CN=fox, OU=fox, O=fox, L=fox, ST=fox, C=fx  
  4. Serial number: 6eaf996f  
  5. Valid from: Wed Nov 05 16:15:41 CST 2014 until: Tue Feb 03 16:15:41 CST 2015  
  6. Certificate fingerprints:  
  7. MD5: B5:B6:92:66:84:92:A0:C2:F5:40:39:25:F8:66:2A:17  
  8. SHA1: 07:42:A3:1A:49:7B:C9:34:4B:6B:FA:37:6C:20:98:D4:20:13:7C:91  
  9. SHA256: 37:A5:00:A3:13:00:DE:99:3B:08:47:F6:1E:8A:05:F1:4A:B2:C6:22:20:  
  10. E1:AF:0E:05:B2:CE:E0:2F:94:B6:94  
  11. Signature algorithm name: SHA1withDSA  
  12. Version: 3  
  13.   
  14. Extensions:  
  15.   
  16. #1: ObjectId: 2.5.29.14 Criticality=false  
  17. SubjectKeyIdentifier [  
  18. KeyIdentifier [  
  19. 0000: 69 3E 6A D0 B5 B1 1F BD 48 46 E1 A4 6C 1F 71 90 i>j.....HF..l.q.  
  20. 0010: 29 06 3B 32 ).;2  
  21. ]  
  22. ]  
  23.   
  24. Trust this certificate? [no]: y  
  25. Certificate was added to keystore</span>  


6)创建client的truststore文件并导入server的证书(其中包括server的公钥)。

  1. <span style="font-family:Verdana;">C:\Program Files\Java\jre7\bin>keytool -import -alias catserver -keystore c:\_tmp\foxclienttrust.keystore -storepass foxclienttrustks -file c:\_tmp\catserver.cer  
  2. Owner: CN=cat, OU=cat, O=cat, L=cat, ST=cat, C=ct  
  3. Issuer: CN=cat, OU=cat, O=cat, L=cat, ST=cat, C=ct  
  4. Serial number: 3e421457  
  5. Valid from: Wed Nov 05 16:13:52 CST 2014 until: Tue Feb 03 16:13:52 CST 2015  
  6. Certificate fingerprints:  
  7. MD5: 20:44:7C:E5:30:E6:7A:21:C2:49:64:77:E1:3A:A0:77  
  8. SHA1: 8B:02:D2:BE:98:2F:99:94:08:47:E2:96:EC:05:1B:5D:B1:8F:30:2F  
  9. SHA256: A6:66:85:F4:C2:B2:06:4E:2E:40:D8:52:84:6E:85:2B:5B:BB:C3:B0:9C:  
  10. 31:92:99:F5:91:5D:83:67:C8:4D:D8  
  11. Signature algorithm name: SHA256withRSA  
  12. Version: 3  
  13.   
  14. Extensions:  
  15.   
  16. #1: ObjectId: 2.5.29.14 Criticality=false  
  17. SubjectKeyIdentifier [  
  18. KeyIdentifier [  
  19. 0000: F5 91 E6 14 EE EF 5F 24 4F AC 6F A6 B8 36 A6 11 ......_$O.o..6..  
  20. 0010: 2B 5C DF 04 +\..  
  21. ]  
  22. ]  
  23.   
  24. Trust this certificate? [no]: y  
  25. Certificate was added to keystore</span>  


keysize
如果加密算法是rsa,key size范围512->16384 bits,并且必须是64的倍数。
如果加密算法是dsa,key size范围512->1024 bits,并且必须是64的倍数。

sigalg
如果加密算法是rsa,签名算法可以是md5withrsa/sha1withrsa/sha256withrsa/sha384withrsa/sha512withrsa
如果加密算法是dsa,签名算法可以是sha1withdsa

如果熟悉Java的socket编程,就会发现使用JSSE进行SSL/TLS编程其实和它很相似。
区别在于ServerSocket对象换成了SSLServerSocket,Socket对象换成了SSLSocket对象。

(二)server端处理流程和代码

处理流程:
1)加载server的keystore文件,需要指定keystore的密码(storepass)。
KeyStore类型有如下三种:
jceks - The proprietary keystore implementation provided by the SunJCE provider.
jks - The proprietary keystore implementation provided by the SUN provider.
pkcs12 - The transfer syntax for personal identity information as defined in PKCS #12.

2)加载server的truststore文件,需要指定truststore的密码(storepass)。

3) 创建KeyManagerFactory对象并用1)中加载的keystore和server密钥对的密码(keypass)来初始化。

4) 创建TrustManagerFactory对象并用2)中加载的truststore来初始化。truststore中存的是client的公钥,不需要keypass也可以访问。

5)创建SSLContext并用3)和4)中创建的KeyManagerFactory和TrustManagerFactory对象来初始化。
http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
创建SSLContext是需要给出SSLContext Algorithms。上面这个链接中给出了合法的SSLContext Algorithms,有如下可用值。
SSL - Supports some version of SSL; may support other versions
SSLv2 - Supports SSL version 2 or later; may support other versions
SSLv3 - Supports SSL version 3; may support other versions
TLS - Supports some version of TLS; may support other versions
TLSv1 - Supports RFC 2246: TLS version 1.0 ; may support other versions
TLSv1.1 - Supports RFC 4346: TLS version 1.1 ; may support other versions
TLSv1.2 - Supports RFC 5246: TLS version 1.2 ; may support other versions

6)创建SSLServerSocketFactory,在指定的端口上创建SSLServerSocket并设定需要客户端证书:setNeedClientAuth(true)

7)在SSLServerSocket对象上调用accept()方法等待客户端的连接。
客户端连上来之后这个函数会返回一个SSLSocket对象,在这个对象的输入输出流上进行读写。
在这个SSLSocket对象上可以添加一个HandshakeCompletedListener的监听器,SSL/TLS握手结束后这个监听器的handshakeCompleted方法就会被调用。
客户端有三种方法会触发握手:
- 显式调用startHandshake方法/calling startHandshake which explicitly begins handshakes, or
- 在socket对象上进行read或write操作/any attempt to read or write application data on this socket causes an implicit handshake, or
- 在socket对象上调用getSession方法/a call to getSession tries to set up a session if there is no currently valid session, and an implicit handshake is done.

  1. <span style="font-family:Verdana;">package learning.net.ssl;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.FileInputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStreamReader;  
  7. import java.io.PrintWriter;  
  8. import java.net.Socket;  
  9. import java.security.KeyStore;  
  10. import java.security.cert.X509Certificate;  
  11.   
  12. import javax.net.ssl.HandshakeCompletedEvent;  
  13. import javax.net.ssl.HandshakeCompletedListener;  
  14. import javax.net.ssl.KeyManagerFactory;  
  15. import javax.net.ssl.SSLContext;  
  16. import javax.net.ssl.SSLPeerUnverifiedException;  
  17. import javax.net.ssl.SSLServerSocket;  
  18. import javax.net.ssl.SSLServerSocketFactory;  
  19. import javax.net.ssl.SSLSocket;  
  20. import javax.net.ssl.TrustManagerFactory;  
  21.   
  22. public class CatServer implements Runnable, HandshakeCompletedListener {  
  23.   
  24.     public static final int SERVER_PORT = 11123;  
  25.   
  26.     private final Socket _s;  
  27.     private String peerCerName;  
  28.   
  29.     public CatServer(Socket s) {  
  30.         _s = s;  
  31.     }  
  32.   
  33.     public static void main(String[] args) throws Exception {  
  34.         String serverKeyStoreFile = "c:\\_tmp\\catserver.keystore";  
  35.         String serverKeyStorePwd = "catserverks";  
  36.         String catServerKeyPwd = "catserver";  
  37.         String serverTrustKeyStoreFile = "c:\\_tmp\\catservertrust.keystore";  
  38.         String serverTrustKeyStorePwd = "catservertrustks";  
  39.   
  40.         KeyStore serverKeyStore = KeyStore.getInstance("JKS");  
  41.         serverKeyStore.load(new FileInputStream(serverKeyStoreFile), serverKeyStorePwd.toCharArray());  
  42.   
  43.         KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS");  
  44.         serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray());  
  45.   
  46.         KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
  47.         kmf.init(serverKeyStore, catServerKeyPwd.toCharArray());  
  48.   
  49.         TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());  
  50.         tmf.init(serverTrustKeyStore);  
  51.   
  52.         SSLContext sslContext = SSLContext.getInstance("TLSv1");  
  53.         sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);  
  54.   
  55.         SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();  
  56.         SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(SERVER_PORT);  
  57.         sslServerSocket.setNeedClientAuth(true);  
  58.   
  59.         while (true) {  
  60.             SSLSocket s = (SSLSocket)sslServerSocket.accept();  
  61.             CatServer cs = new CatServer(s);  
  62.             s.addHandshakeCompletedListener(cs);  
  63.             new Thread(cs).start();  
  64.         }  
  65.     }  
  66.   
  67.     @Override  
  68.     public void run() {  
  69.         try {  
  70.             BufferedReader reader = new BufferedReader(new InputStreamReader(_s.getInputStream()));  
  71.             PrintWriter writer = new PrintWriter(_s.getOutputStream(), true);  
  72.   
  73.             writer.println("Welcome~, enter exit to leave.");  
  74.             String s;  
  75.             while ((s = reader.readLine()) != null && !s.trim().equalsIgnoreCase("exit")) {  
  76.                 writer.println("Echo: " + s);  
  77.             }  
  78.             writer.println("Bye~, " + peerCerName);  
  79.         } catch (Exception e) {  
  80.             e.printStackTrace();  
  81.         } finally {  
  82.             try {  
  83.                 _s.close();  
  84.             } catch (IOException e) {  
  85.                 e.printStackTrace();  
  86.             }  
  87.         }  
  88.     }  
  89.   
  90.     @Override  
  91.     public void handshakeCompleted(HandshakeCompletedEvent event) {  
  92.         try {  
  93.             X509Certificate cert = (X509Certificate) event.getPeerCertificates()[0];  
  94.             peerCerName = cert.getSubjectX500Principal().getName();  
  95.         } catch (SSLPeerUnverifiedException ex) {  
  96.             ex.printStackTrace();  
  97.         }  
  98.     }  
  99.   
  100. }</span>  


(三)client端处理流程和代码

处理流程:(1~5和server相同)
1)加载client的keystore文件。

2)加载client的truststore文件。

3) 创建KeyManagerFactory对象并初始化。

4) 创建TrustManagerFactory对象并初始化。truststore中存的是server的公钥,不需要keypass也可以访问。

5)创建SSLContext并用3)和4)中创建的KeyManagerFactory和TrustManagerFactory对象来初始化。

6)创建SSLSocketFactory,在指定的网络地址和端口上创建SSLSocket。

7)在这个SSLSocket对象的输入输出流上进行读写。

  1. <span style="font-family:Verdana;">package learning.net.ssl;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.FileInputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStreamReader;  
  7. import java.io.PrintWriter;  
  8. import java.net.Socket;  
  9. import java.security.KeyStore;  
  10.   
  11. import javax.net.ssl.KeyManagerFactory;  
  12. import javax.net.ssl.SSLContext;  
  13. import javax.net.ssl.SSLSocketFactory;  
  14. import javax.net.ssl.TrustManagerFactory;  
  15.   
  16. public class FoxClient {  
  17.     public static void main(String[] args) throws Exception {  
  18.         String clientKeyStoreFile = "c:\\_tmp\\foxclient.keystore";  
  19.         String clientKeyStorePwd = "foxclientks";  
  20.         String foxclientKeyPwd = "foxclient";  
  21.         String clientTrustKeyStoreFile = "c:\\_tmp\\foxclienttrust.keystore";  
  22.         String clientTrustKeyStorePwd = "foxclienttrustks";  
  23.   
  24.         KeyStore clientKeyStore = KeyStore.getInstance("JKS");  
  25.         clientKeyStore.load(new FileInputStream(clientKeyStoreFile), clientKeyStorePwd.toCharArray());  
  26.   
  27.         KeyStore clientTrustKeyStore = KeyStore.getInstance("JKS");  
  28.         clientTrustKeyStore.load(new FileInputStream(clientTrustKeyStoreFile), clientTrustKeyStorePwd.toCharArray());  
  29.   
  30.         KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
  31.         kmf.init(clientKeyStore, foxclientKeyPwd.toCharArray());  
  32.   
  33.         TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());  
  34.         tmf.init(clientTrustKeyStore);  
  35.   
  36.         SSLContext sslContext = SSLContext.getInstance("TLSv1");  
  37.         sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);  
  38.           
  39.         SSLSocketFactory socketFactory = sslContext.getSocketFactory();  
  40.         Socket socket = socketFactory.createSocket("localhost", CatServer.SERVER_PORT);  
  41.           
  42.         PrintWriter out = new PrintWriter(socket.getOutputStream(), true);  
  43.         BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  44.           
  45.         send("hello", out);  
  46.         send("exit", out);  
  47.         receive(in);  
  48.         socket.close();  
  49.     }  
  50.       
  51.     public static void send(String s, PrintWriter out) throws IOException {  
  52.         System.out.println("Sending: " + s);       
  53.         out.println(s);  
  54.     }  
  55.   
  56.     public static void receive(BufferedReader in) throws IOException {  
  57.         String s;  
  58.         while ((s = in.readLine()) != null) {  
  59.             System.out.println("Reveived: " + s);  
  60.         }  
  61.     }  
  62. }</span>  


(四)使用Openssl进行证书签名

如果需要对证书进行签名,可以使用keytool生成一个csr(certificate sign request), 然后提交到一个CA进行签名。这里使用openssl提供的CA功能。

1)[openssl]生成CA的RSA私钥。
bash-3.00$ openssl genrsa -out cakey.pem 1024

2)[openssl]使用CA.sh脚本初始化CA。脚本会要求输入刚才生成的私钥文件。
bash-3.00$ CA.sh -newca
CA certificate filename (or enter to create)
cakey.pem

3)[openssl]利用CA私钥生成自签名的CA根证书。
指定x509参数表示要生成自签名的证书。(我们知道证书里面只包含公钥,为什么从私钥可以生成证书呢?这是因为私钥里面包含RSA算法所需的参数,其实可以算出公钥,后面会详细解释)
bash-3.00$ openssl req -new -x509 -key cakey.pem -out ca.cer -config openssl.cnf
(linux上openssl.cnf的路径/etc/pki/tls/openssl.cnf,可以拷贝一份到当前目录)

4)[keytool]生成server的keystore文件。
C:\Program Files\Java\jre7>keytool -genkey -alias catserver -keyalg rsa -keysize 1024 -sigalg sha256withrsa -keypass catserver -keystore c:\_tmp\catserver.keystore -storepass catserverks

5)[keytool]生成server的csr.
C:\Program Files\Java\jre7>keytool -certreq -alias catserver -file c:\_tmp\catserver.csr -keypass catserver -keystore c:\_tmp\catserver.keystore -storepass catserverks

6) [openssl]对server的csr进行签名得到server证书
bash-3.00$ openssl ca -in catserver.csr -out catserver.cer -cert ca.cer -keyfile cakey.pem -config openssl.cnf
(如果是因为权限问题,不能访问CA的newcerts目录,可以先进行如下操作:
bash-3.00$ mkdir newcerts 
bash-3.00$ touch index.txt 
bash-3.00$ echo 01 > serial)

7)[keytool]生成client的keystore文件。
C:\Program Files\Java\jre7>keytool -genkey -alias foxclient -keyalg dsa -keysize 512 -sigalg sha1withdsa -keypass foxclient -keystore c:\_tmp\foxclient.keystore -storepass foxclientks

8)[keytool]生成client的csr.
C:\Program Files\Java\jre7>keytool -certreq -alias foxclient -file c:\_tmp\foxclient.csr -keypass foxclient -keystore c:\_tmp\foxclient.keystore -storepass foxclientks

9) [openssl]对client的csr进行签名得到client证书
bash-3.00$ openssl ca -in foxclient.csr -out foxclient.cer -cert ca.cer -keyfile cakey.pem -config openssl.cnf

现在我们有如下文件:
catserver.keystore -- server的keystore文件
catserver.cer -- server证书文件,已经由CA签名。

foxclient.keystore -- client的keystore文件
foxclient.cer -- client证书文件,已经由CA签名。

ca.cer -- CA的证书文件。作为根证书。

接下来我们还需要
10)[keytool]导入ca.cer和catserver.cer到catserver.keystore
keytool -import -trustcacerts -alias ca -keystore c:\_tmp\catserver.keystore -storepass catserverks -file c:\_tmp\ca.cer
keytool -import -alias catserver -keypass catserver -keystore c:\_tmp\catserver.keystore -storepass catserverks -file c:\_tmp\catserver.cer

11)[keytool]导入ca.cer和foxclient.cer到foxclient.keystore
keytool -import -trustcacerts -alias ca -keystore c:\_tmp\foxclient.keystore -storepass foxclientks -file c:\_tmp\ca.cer
keytool -import -alias foxclient -keypass foxclient -keystore c:\_tmp\foxclient.keystore -storepass foxclientks -file c:\_tmp\foxclient.cer

12)[keytool]创建server的truststore文件并导入ca.cer和foxclient.cer.
keytool -import -trustcacerts -alias ca -keystore c:\_tmp\catservertrust.keystore -storepass catservertrustks -file c:\_tmp\ca.cer
keytool -import -alias foxclient -keystore c:\_tmp\catservertrust.keystore -storepass catservertrustks -file c:\_tmp\foxclient.cer

13)[keytool]创建client的truststore文件并导入ca.cer和catserver.cer.
keytool -import -trustcacerts -alias ca -keystore c:\_tmp\foxclienttrust.keystore -storepass foxclienttrustks -file c:\_tmp\ca.cer
keytool -import -alias catserver -keystore c:\_tmp\foxclienttrust.keystore -storepass foxclienttrustks -file c:\_tmp\catserver.cer


*前面提到可以从CA的私钥文件生成CA的根证书。证书里面其实包含的是公钥。
其实openssl也提供命令可以直接从私钥cakey.pem生成公钥。
openssl rsa -in cakey.pem -pubout -out caputkey.pem
为什么能够从私钥推导出公钥呢?
这需要了解RSA算法-〉http://blog.youkuaiyun.com/fw0124/article/details/41118525
原因很简单,因为私钥中也包含了计算公钥所需的参数n和e。

*可以使用openssl来生成server的证书,步骤如下
openssl genrsa -out catserverkey.pem 1024
openssl req -new -key catserverkey.pem -out catserver.csr -config openssl.cnf
openssl ca -in catserver.csr -out catserver.cer -cert ca.cer -keyfile cakey.pem -config openssl.cnf

=====================================

如果openssl ca ...进行签名的时候碰到
The stateOrProvinceName field needed to be the same in the ...的错误,可以修改openssl.cnf文件:
[ policy_match ]
countryName             = optional
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional

如果遇到
failed to update database
TXT_DB error number 2     的错误,
删除index.txt,并再touch下


如果keytool -import命令导入签名后的证书的时候遇到以下错误
keytool 错误: java.lang.Exception: 无法从回复中建立链
重新导入下ca.cer即可。
keytool -delete -alias ca -keystore c:\_tmp\catserver.keystore -storepass catserverks
keytool -import -trustcacerts -alias ca ...

======================================

CER文件到PEM文件的转换较简单。这两者都是X509证书,编码不同,使用openssl工具即可:

openssl x509 -informder -in catserver.cer -out catserver.pem


(五)如何从.keystore文件中导出私钥

Keytool不支持直接从.keystore中导出私钥。但是可以把JKS文件转换成openssl支持的PKCS#12格式的文件。

所以可以通过下面2步来从.keystore中导出私钥。

➜ ~ keytool -importkeystore -srckeystore catserver.keystore -destkeystore catserver.p12 -deststoretype PKCS12 -srcalias catserver -srcstorepass catserverks -srckeypass catserver -deststorepass catserverks -destkeypass catserver
Warning: Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified -destkeypass value.
➜  ~  openssl pkcs12 -in catserver.p12  -nodes -nocerts -out catserverkey.pem
Enter Import Password:
MAC verified OK
➜  ~

*-nodes选项意思是No DES,即不加密导出的私钥。


Java-JSSE-SSL/TLS编程代码实例-单向认证 使用JSSE实现一个单向认证的SSL/TLS编程代码实例。 阅读详情

相关推荐

使用wireshark观察SSL/TLS握手过程--双向认证/单向认证

SSL/TLS握手过程实际上就是通信双方协商交换一个用于对称加密的密钥的过程。 这个过程实际上产生三个随机数:client random, server random, pre-master secret。 前两个随机数都是明文传送的,只有pre-master secret是加密的(RSA或者DH)。 一般生成证书的时候,签名算法可以选择RSA或者DSA算法。 如果server使用RSA证书,RSA即可以用作签名也可以用作不对称加密,pre-master secret就是用server的RSA证书中包含的公

NowOrNever 6万+

java后台开发入门(springboot快速入门)

带领大家借助当下比较流行的springboot框架快速开发属于自己的java后台。即便你是编程小白,没有任何编程基础也可以学习本课程。知识点1,Java2,springboot3,freemarker4,bootstrap4.35,Javaweb6,微信小程序同时会借助当下最热门的微信小程序来作为我们的前端展示。所以课程中也会教给大家一部分小程序开发的知识。大家只需要跟着老师一步步学习,我们既可以学习到java知识,也可以学习到小程序开发和web开发相关的知识。我们学习过程中会有老师在线实时解答,每节课都会有对应的源码和配套笔记给到大家。

Android JSSE实现SSL双向认证(阻塞模式及非阻塞模式)

一、概念及相关术语定义 SSL双向认证:SSL协商时默认只认证Server侧,即客户端(浏览器等)总是需要验证服务器端的数字证书。但在某些场合,为了验证用户的有效性,例如,登录网上银行及一些敏感的服务器时就需要用户提供自己的有效数字证书(如U盾等)。而用户数字证书被加载和鉴证的SSL协商或者重协商的过程便是SSL的双向认证。 JSSE: (Java 安全套接字扩展,Java Secure So

hrp36的专栏 1629

【亲测免费】 OpenJSSE:为Java 8带来TLS 1.3支持的开源利器

OpenJSSE:为Java 8带来TLS 1.3支持的开源利器 项目介绍 OpenJSSE 是一个为Java SE 8环境提供TLS 1.3支持的JSSE(Java Secure Socket Extension)提供者。该项目的主要目标是让现有的Java 8应用程序无需修改代码即可支持TLS 1.3,同时为开发者提供一种编程方式来访问Java SE 8 API中未直接提供的TLS 1.3和RS...

gitblog_00104的博客 1349

Java实现SSL/TLS通信系统:从证书配置到JSSE实战

在Java网络编程中,安全通信始终是工程实践的关键课题。从基础的TCP Socket通信到加密传输,SSL/TLS协议为数据传输提供了机密性、完整性与身份认证保障。Java标准库中的JSSE(Java Secure Socket Extension)封装了TLS握手、证书校验、密钥协商等核心机制,开发者无需引入第三方依赖即可构建安全的通信系统。理解单向认证与双向认证的差异,掌握KeyStore与TrustStore的配置方法,是落地此类系统的前提。无论是课程设计还是企业级应用,基于Java实现SSL/TLS

weixin_32705179的博客 239

Java国密HTTPS通信实战:基于gm-jsse的JSSE SPI实现与双向认证

在Java安全通信领域,JSSE(Java Secure Socket Extension)是构建HTTPS、SSL/TLS连接的标准API框架,其核心机制SPI(Service Provider Interface)允许开发者插入自定义的安全提供者。国密算法(SM2/SM3/SM4)作为我国自主的商用密码标准,在金融、政务等对数据安全与合规性要求极高的场景中已成为强制或推荐规范。传统集成方式往往依赖第三方密码库进行繁琐配置,难以与原生JSSE API无缝融合。gm-jsse项目通过实现完整的JSSE SP

weixin_28622215的博客 380

【ssl认证、证书】SSL双向认证java实战、keytool创建证书

模拟场景:Server端和Client端通信,需要进行授权和身份的验证,即Client只能接受Server的消息,Server只能接受Client的消息。实现技术:是Sun为了解决在Internet上的安全通讯而推出的解决方案。它实现了SSL和TSL(传输层安全)协议。在JSSE中包含了数据加密,服务器验证,消息完整性和客户端验证等技术。通过使用JSSE,开发人员可以在客户机和服务器之间通过TCP/IP协议安全地传输数据为了实现消息认证。Server需要:1)KeyStore。

m0_45406092的博客 2271

Java SSL Socket双向认证实现详解与实战

Java Secure Socket Extension(JSSE)是Java平台中实现SSL/TLS协议的核心API,为开发者提供了构建安全网络通信的标准化接口。作为Java SE的一部分,JSSE从JDK 1.4起被正式集成,并持续演进以支持最新的加密算法和安全协议版本(如TLS 1.3)。其设计目标是在不破坏原有Socket编程模型的前提下,无缝嵌入加密、身份认证与数据完整性保护机制。

weixin_28840811的博客 605

SSL Socket 双向认证

一、简介

u014548782的专栏 3806

TLS java简单实现

NULL 博文链接:https://antlove.iteye.com/blog/2166171

JAVA实现的SSL/TLS双向认证源代码

压缩包里有客户端源码和服务器端源码,支持TCP的双向认证,也支持WEBSOCKET的双向认证,内附测试 wss的测试例子, 需要生成PKCS12的证书,导入浏览器才可以测试。

HTTPS安全通讯 5. Java 使用JSSE实现SSL/TLS安全协议

一、简介 JSSE包含了实现Internet安全通信的一系列包的集合,是SSL和TLS的纯Java实现。用JSSE可以像使用普通的套接字一样使用安全套接字。 1. 一些概念 1.1.1 证书产生方式 证书会描述所有者的一些基本信息,如公司名称、联系人等。证书由所有人以密码形式签名。获取方式一般两个: 权威机构购买证书 自己用JDK的keytool创建自我签名的证书。这种情况下一般为了防止数据被篡改,身份认证不是主要目的。 1.1.2 密钥存储格式转换说明 1.1.3 keytool导入 pkcs#12

猿来这样-谢厂节的博客 1243

把对讲门铃(控制底楼铁门)接入米家服务器

今天讲个跟SDR或者无人机无关的东西,技术含量不高,但是方便了我的生活。 现在家门有智能锁,汽车也可以远程解锁发动,NFC门禁也可以用某些手机复制,唯独楼下的铁门,必须用老式对讲门铃控制。 也就是说其它钥匙都可以不带,就剩这个钥匙还必须随身携带。 另外有时候人不在家,不能开楼下铁门,快递员也没法把东西送上楼。 ......

老邵的开源世界 6551

Java SSL/TLS 安全通讯协议(SSLSocket)

简介: 本文主要介绍了网络安全通讯协议 SSL/TLS 和 Java 中关于安全通讯的实现部分。并通过一个简单的样例程序实现,来展示如何在 Java 平台上正确建立安全通讯。 在人类建立了通信系统之后,如何保证通信的安全始终是一个重要的问题。伴随着现代化通信系统的建立,人们利用数学理论找到了一些行之有效的方法来保证数字通信的安全。简单来说就是把两方通信的过程进行保密处理,比如对双

cyl937的专栏 5221

Android安全支付(1)-整体架构-keymint

(1)接口定义hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl。keymint是keymaster v4之后的替代设计。所以android 15上最好采用keymint的接口进行硬件功能的对接。同时,我们会集成一款紫光的芯片。3.可以用keyStore.getKey()来获取存储在keyStore中的数据进行加密和解密。四、关于keymint的接口定义和具体实现。

Android系统开发-VR OS-系统安全隐私 1770

ESP32-S3 + TB6600驱动42步进电机:从基础接线到AccelStepper库平滑加减速实战

本文详细介绍了如何使用ESP32-S3开发板和TB6600驱动器控制42步进电机,从基础接线到利用AccelStepper库实现平滑加减速控制。内容涵盖硬件连接、基础驱动代码、AccelStepper库的安装与参数调优,以及高级技巧与故障排除,帮助创客实现工业级精准控制。

weixin_42632434的博客 284

Java SSL/TLS 安全通讯协议介绍

Java 的安全通讯 本文主要介绍了网络安全通讯协议 SSL/TLS 和 Java 中关于安全通讯的实现部分。并通过一个简单的样例程序实现,来展示如何在 Java 平台上正确建立安全通讯。 0 评论: 刘 进, 高级软件工程师 , IBM 关闭 [x] 刘进目前在 IBM STG 云计算团队从事云管理平台产品开发,拥有十年的 Java

yumeng8525的专栏 1423

三菱FX5U运动控制(步进)

三菱FX5U脉冲定位控制,原点回归,相对定位,绝对定位,运动控制案例。

weixin_55762091的博客 1万+

TCP、TLS\SSL、JSSE、HTTPS杂烩笔记

以目前我的理解以及这两天的各种百度写个总结笔记,有不对的请指正 TCP 简介 全名Transmission Control Protocol,传输控制协议,是网络层IP协议和链路层Ethernet协议之上,Ethernet协议实现链路层的数据传输和地址封装(源方和目标方的MAC地址),解决局域网的点对点通信,而不同局域网之间的两台机子则需要IP协议进行地址的路由中转,TCP则面向的是端口到端口,保证数据传输的完整和可靠,包括数据包的确认、失败重发、流量控制,数据量大的情况TCP会将数据拆分为有

xyjy11的博客 2206

一文读懂世界模型(World Model):AI的“数字大脑”,通往AGI的核心基石

世界模型正成为AI领域的关键技术,它让AI在虚拟环境中模拟物理世界规律并预测行动后果,从而减少现实试错成本。2018年Ha和Schmidhuber提出的VAE+RNN架构奠定基础,2022年后自监督学习推动快速发展。当前世界模型分为潜空间、生成式、强化学习和对象中心四大流派,已在机器人、自动驾驶、工业仿真等领域落地应用。尽管面临长时序预测误差等挑战,未来将向多模态建模、大模型融合等方向发展,成为实现具身智能和通用人工智能的核心基石。

m0_38116472的博客 811

MATLAB船舶开尔文尾迹三维仿真建模

开尔文尾迹介绍 Kelvin最早研究舰船在水面运动在水面上形成波纹的原理,主要针对静水中点源运动的尾迹问题,并给出尾迹的张角和波高分布情况。由 Kelvin 的理论,一般情况下假设由一个理想点源来代替舰船,开尔文尾迹由分歧波和横断波组成,分歧波向船的两侧扩散,而横断波主要向船的后方传播,在相遇的地方两波相干形成尖头波,且尖头波位于尾迹角16°到19.5°之间,又因为尖头波波长过短,以至于无法单独的区分出每个尖头波的波前,所有的波前在视觉效果上就连成一条直线表现为亮线,称为开尔文臂,开尔文臂以船身对称,且角度

qq_19512613的博客 3845
上一篇: Java不同类型密钥库之PKCS12和JCEKS
下一篇: HttpClient使用详解
lcathm
博客等级 码龄18年 37粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值