遇到網站使用自訂 CA 憑證簽發 SSL 憑證,在 Windows 及 .NET 程式需手動匯入並信任 CA 根憑證(做法可參考 使用 OpenSSL 建立 CA 及簽發 SSL 憑證)解決憑證不安全連線被拒問題,但 Java 程式有自己的憑證信任機制,設定方式不同。

為快速驗證 CA 根憑證是否生效,我想要類似 openssl 之類的檢測程式,能輸入 URL 一秒知道結果,才能符合我的急躁性格做事較有效率。爬文查到這篇 Use SSL Poke to test Java SSL connection 介紹 Atlassian (Bitbucket 背後的公司) 寫的小工具 SSL Poke:

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;

/** Establish a SSL connection to a host and port, writes a byte and
 * prints the response. See
 * http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services
 */
public class SSLPoke {
    public static void main(String[] args) {
		if (args.length != 2) {
			System.out.println("Usage: "+SSLPoke.class.getName()+" <host> <port>");
			System.exit(1);
		}
		try {
			SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
			SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1]));

			InputStream in = sslsocket.getInputStream();
			OutputStream out = sslsocket.getOutputStream();

			// Write a test byte to get a reaction :)
			out.write(1);

			while (in.available() > 0) {
				System.out.print(in.read());
			}
			System.out.println("Successfully connected");

		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}
}

看不懂沒關係,只要作業系統有裝 JDK,將程式存成 SSLPoke.java,javac SSLPoke.java 編譯成 SSLPoke.class,java SSLPoke xxx.xxx.xxx 443 執行就成了,Java 麻瓜如我也能上手。

若網站的 CA 根憑證未被信任,會得到如下圖 PKIX path building failed、unable to find valid certification path to request target 錯誤:

如果手邊沒有 CA 根憑證,也可以用 openssl 連上網站現場抓(openssl 安裝 Git 工具時會一併安裝,但更省事的方法是開 Cmder),做法是用指令 openssl s_client -connect xxx.xxx.xxx:443 -showcerts > all-certs.txt 將憑證鏈匯出到 all-certs.txt,由名稱找到 CA 根憑證位置,將 -----BEGIN CERTIFICATE----- 到 -----END CERTIFICATE----- 連同 BEGIN CERTIFICATE、END CERTIFICATE 的內容複製另存成「CA憑證名稱.cer」:

接下來我們要用 keytool 工具將 .cer 安裝到 Java 的 cacerts。首先要找到 Java cacerts 的位置,會依安裝的 OpenJDK 版本而不同,我慣用的做法是用 where java 找到 OpenJDK 或 JRE bin 目錄,bin\..\lib\security\cacerts 推算,再用 keytool -import -v -trustcacerts -alias "EntRootCA" -file root-ca.cer -keystore "C:\Program Files\Microsoft\jdk-11.0.11.9-hotspot\lib\security\cacerts" 完成安裝:參考文件:利用keytool 匯入CA Root 憑證方式 by 寰宇數位認證中心

安裝完成重新用 SSLPoke 測試,現在 Java 程式認識我們的自訂根憑證,就不會再抱怨有問題囉,搞定收工。

This article showing how to install and trust CA root cert for Java.


Comments

# by Jeffrey

to 余小章,感謝分享。(我有愈來愈不愛用 GUI 的傾向 XD)

# by will tsai !

跪了! 這篇, 對JAVA 不太熟的小弟我 真是獲益良多! 感謝! client端要做HTTPS (尤其是自簽或不信任等種種原因) 。 1. 手邊沒有 CA 根憑證,也可以用 openssl 連上網站現場抓..............(原來可以直接抓它的根憑證來用). 2. 大絕招..還是得CA憑證弄進入JAVA環境的cacerts! (學習了)

Post a comment