一 證書的制作
進入jdk/bin,使用keytools.exe制作證書。
1.創建keystore
創建一個別名為serverkeystore的證書,該證書存放在名為server.keystore的密鑰庫中,若server.keystore密鑰庫不存在則創建
keytool -genkeypair -alias "serverkeystore" -keyalg "RSA" -keystore "d:/server.keystore"
注意:如果提示下圖錯誤,本人Jdk裝載c盤當中,而C盤都是只讀文件,在c盤當中生成 文件的話,是沒有寫入權限的。所以指定生成 server.keystore在D盤。
2.導出證書
keytool -export -alias serverkeystore -file d:/server.crt -keystore d:/server.keystore
3.使用2中導出的證書生成truestkeystore
keytool -import -v -file D:/server.crt -keystore D:/trustserver.keystore
同理我們在為client制作同樣的文件。
二 代碼中證書文件的使用
server
package com.xiaodeyao; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import java.io.*; import java.net.Socket; import java.security.KeyStore; public class HttpsServer { private static final int DEFAULT_PORT = 7777; private static final String SERVER_KEY_STORE_PASSWORD = "123456"; private static final String SERVER_TRUST_KEY_STORE_PASSWORD = "123456"; private SSLServerSocket serverSocket; public static void main(String[] args) { HttpsServer server = new HttpsServer(); server.init(); server.start(); } /** * <ul> * <li>聽SSL Server Socket</li> * <li> 由於該程序不是演示Socket監聽,所以簡單采用單線程形式,並且僅僅接受客戶端的消息,並且返回客戶端指定消息</li> * </ul> */ public void start() { if (serverSocket == null) { System.out.println("ERROR"); return; } while (true) { try { Socket s = serverSocket.accept(); InputStream input = s.getInputStream(); OutputStream output = s.getOutputStream(); BufferedInputStream bis = new BufferedInputStream(input); BufferedOutputStream bos = new BufferedOutputStream(output); byte[] buffer = new byte[20]; bis.read(buffer); System.out.println(new String(buffer)); bos.write("Server Echo".getBytes()); bos.flush(); s.close(); } catch (Exception e) { System.out.println(e); } } } /** * <ul> * <li>ssl連接的重點:</li> * <li>初始化SSLServerSocket</li> * <li>導入服務端私鑰KeyStore,導入服務端受信任的KeyStore(客戶端的證書)</li> * </ul> */ public void init() { try { SSLContext ctx = SSLContext.getInstance("SSL"); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); KeyStore ks = KeyStore.getInstance("JKS"); KeyStore tks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream("D://server.keystore"), SERVER_KEY_STORE_PASSWORD.toCharArray()); tks.load(new FileInputStream("D://trustclient.keystore"), SERVER_TRUST_KEY_STORE_PASSWORD.toCharArray()); kmf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray()); tmf.init(tks); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(DEFAULT_PORT); serverSocket.setNeedClientAuth(true); } catch (Exception e) { e.printStackTrace(); } } }
client
package com.xiaodeyao; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManagerFactory; import java.io.*; import java.security.KeyStore; public class HttpsClient { private static final String DEFAULT_HOST = "127.0.0.1"; private static final int DEFAULT_PORT = 7777; private static final String CLIENT_KEY_STORE_PASSWORD = "123456"; private static final String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456"; private SSLSocket sslSocket; /** * 啟動客戶端程序 * * @param args */ public static void main(String[] args) { HttpsClient client = new HttpsClient(); client.init(); client.process(); } /** * 通過ssl socket與服務端進行連接,並且發送一個消息 */ public void process() { if (sslSocket == null) { System.out.println("ERROR"); return; } try { InputStream input = sslSocket.getInputStream(); OutputStream output = sslSocket.getOutputStream(); BufferedInputStream bis = new BufferedInputStream(input); BufferedOutputStream bos = new BufferedOutputStream(output); bos.write("Client Message".getBytes()); bos.flush(); byte[] buffer = new byte[20]; bis.read(buffer); System.out.println(new String(buffer)); sslSocket.close(); } catch (IOException e) { System.out.println(e); } } /** * <ul> * <li>ssl連接的重點:</li> * <li>初始化SSLSocket</li> * <li>導入客戶端私鑰KeyStore,導入客戶端受信任的KeyStore(服務端的證書)</li> * </ul> */ public void init() { try { SSLContext ctx = SSLContext.getInstance("SSL"); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); KeyStore ks = KeyStore.getInstance("JKS"); KeyStore tks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream("D://client.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray()); tks.load(new FileInputStream("D://trustserver.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray()); kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray()); tmf.init(tks); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT); } catch (Exception e) { System.out.println(e); } } }
參考: