0x00 緒言
通過 java 執行 https 請求時可能出現以下錯誤:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
這是因為 java 在執行 SSL/TLS 通訊時使用特定的數據識別 Certificate Authorities(CA),如果你試圖發起的 SSL/TLS 連接使用不屬于這些根證書機構所頒發的證書,就會拋出
SunCertPathBuilderException: unable to find valid certification path to requested target
因此,如果你使用自簽名證書,或者根證書機構不在 JRE 默認信任列表中,則需要向 JRE 導入根證書。
最近我們有個項目使用了沃通的免費 SSL 證書,因其根證書屬于 StartSSL 并不在 JRE 默認信任列表中,因此簡單記錄下導入過程。
0x01 導入根證書到 JRE
首先,我們需要獲取根證書:
mkdir ~/tmp
cd ~/tmp
curl http://www.startssl.com/certs/ca.crt -O
curl http://www.startssl.com/certs/sub.class1.server.ca.crt -O
curl http://www.startssl.com/certs/sub.class2.server.ca.crt -O
curl http://www.startssl.com/certs/sub.class3.server.ca.crt -O
curl http://www.startssl.com/certs/sub.class4.server.ca.crt -O
然后,將證書導入到 JRE 信任列表:
sudo keytool -import -trustcacerts -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -noprompt -alias startcom.ca -file ca.crt
sudo keytool -import -trustcacerts -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -noprompt -alias startcom.ca.sub.class1 -file sub.class1.server.ca.crt
sudo keytool -import -trustcacerts -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -noprompt -alias startcom.ca.sub.class2 -file sub.class2.server.ca.crt
sudo keytool -import -trustcacerts -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -noprompt -alias startcom.ca.sub.class3 -file sub.class3.server.ca.crt
sudo keytool -import -trustcacerts -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -noprompt -alias startcom.ca.sub.class4 -file sub.class4.server.ca.crt
別奇怪,"changeit" 只是個默認密碼而已。
最后,驗證一下導入是否成功:
keytool -keystore "/Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre/lib/security/cacerts" -storepass changeit -list | grep start
輸出:
startcom.ca, 2015-11-3, trustedCertEntry,
startcom.ca.sub.class4, 2015-11-3, trustedCertEntry,
startcom.ca.sub.class3, 2015-11-3, trustedCertEntry,
startcom.ca.sub.class2, 2015-11-3, trustedCertEntry,
startcom.ca.sub.class1, 2015-11-3, trustedCertEntry,
It's OK!