特別提示:本人博客部分有參考網絡其他博客,但均是本人親手編寫過並驗證通過。如發現博客有錯誤,請及時提出以免誤導其他人,謝謝!歡迎轉載,但記得標明文章出處:
http://www.cnblogs.com/mao2080/
1、問題描述
Java客服端使用證書連接到服務器,加密方式有了兩種:方式一:CA、Client CRT、Client Key 文件 | 方式二:KeyStore.jks、TrustStore.jks、Password。
2、操作方法
1、通過 CA、Client CRT、Client Key,客戶端自己創建 KeyStore、TrustStore,再創建 SSLSocketFactory
1 /** 2 * 創建 SSLSocketFactory 工廠 3 * 4 * @param caCrtFile 服務端 CA 證書 5 * @param crtFile 客戶端 CRT 文件 6 * @param keyFile 客戶端 Key 文件 7 * @param password SSL 密碼,隨機 8 * @return {@link SSLSocketFactory} 9 * @throws Exception 異常 10 */ 11 public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception { 12 InputStream caInputStream = null; 13 InputStream crtInputStream = null; 14 InputStream keyInputStream = null; 15 try { 16 Security.addProvider(new BouncyCastleProvider()); 17 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 18 // load CA certificate 19 caInputStream = new ClassPathResource(caCrtFile).getInputStream(); 20 X509Certificate caCert = null; 21 while (caInputStream.available() > 0) { 22 caCert = (X509Certificate) cf.generateCertificate(caInputStream); 23 } 24 // load client certificate 25 crtInputStream = new ClassPathResource(crtFile).getInputStream(); 26 X509Certificate cert = null; 27 while (crtInputStream.available() > 0) { 28 cert = (X509Certificate) cf.generateCertificate(crtInputStream); 29 } 30 31 // load client private key 32 keyInputStream = new ClassPathResource(keyFile).getInputStream(); 33 PEMParser pemParser = new PEMParser(new InputStreamReader(keyInputStream)); 34 Object object = pemParser.readObject(); 35 PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray()); 36 JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); 37 KeyPair key; 38 if (object instanceof PEMEncryptedKeyPair) { 39 System.out.println("Encrypted key - we will use provided password"); 40 key = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv)); 41 } else { 42 System.out.println("Unencrypted key - no password needed"); 43 key = converter.getKeyPair((PEMKeyPair) object); 44 } 45 pemParser.close(); 46 47 // CA certificate is used to authenticate server 48 KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType()); 49 caKs.load(null, null); 50 caKs.setCertificateEntry("ca-certificate", caCert); 51 TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); 52 tmf.init(caKs); 53 54 // client key and certificates are sent to server so it can authenticate 55 // us 56 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 57 ks.load(null, null); 58 ks.setCertificateEntry("certificate", cert); 59 ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert}); 60 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 61 kmf.init(ks, password.toCharArray()); 62 63 // finally, create SSL socket factory 64 SSLContext context = SSLContext.getInstance("TLSv1.2"); 65 context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 66 67 return context.getSocketFactory(); 68 69 } 70 finally { 71 if (null != caInputStream) { 72 caInputStream.close(); 73 } 74 if (null != crtInputStream) { 75 crtInputStream.close(); 76 } 77 if (null != keyInputStream) { 78 keyInputStream.close(); 79 } 80 } 81 }
2、服務端提供 KeyStore.jks、TrustStore.jks,創建 SSLSocketFactory
1 /** 2 * 創建 SSLSocketFactory 工廠 3 * 4 * @param keyStoreJks 客戶端 KeyStore 5 * @param trustStoreJks 客戶端 信任庫 trust store 6 * @param password 密碼 7 * @return {@link SSLSocketFactory} 8 * @throws Exception 異常 9 */ 10 public static SSLSocketFactory getSocketFactory(final String keyStoreJks, final String trustStoreJks, final String password) throws Exception { 11 InputStream keyStoreJksInputStream = null; 12 InputStream trustStoreJksInputStream = null; 13 try { 14 ClassPathResource classPathResource = new ClassPathResource(keyStoreJks); 15 keyStoreJksInputStream = classPathResource.getInputStream(); 16 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 17 ks.load(keyStoreJksInputStream, password.toCharArray()); 18 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 19 kmf.init(ks, password.toCharArray()); 20 21 classPathResource = new ClassPathResource(trustStoreJks); 22 trustStoreJksInputStream = classPathResource.getInputStream(); 23 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 24 trustStore.load(trustStoreJksInputStream, password.toCharArray()); 25 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); 26 trustManagerFactory.init(trustStore); 27 28 // finally, create SSL socket factory 29 SSLContext context = SSLContext.getInstance("TLSv1.2"); 30 context.init(kmf.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); 31 return context.getSocketFactory(); 32 } 33 finally { 34 try { 35 if (null != keyStoreJksInputStream) { 36 keyStoreJksInputStream.close(); 37 } 38 } catch (IOException e) { 39 System.out.println(e.getMessage()); 40 } 41 42 try { 43 if (null != trustStoreJksInputStream) { 44 trustStoreJksInputStream.close(); 45 } 46 } catch (IOException e) { 47 System.out.println(e.getMessage()); 48 } 49 } 50 }
3、參考網站
https://blog.csdn.net/weixin_43803007/article/details/105513034(原文地址)