Java信任自签名证书
场景
Java程序中访问HTTPS资源,如果使用了自签名证书,大概率会报如下错误:
text
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
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1640)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:167)
at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:732)
at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:707)
at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:297)
at Test.main(Test.java:22)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
at sun.security.validator.Validator.validate(Validator.java:262)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:330)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:237)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1622)
... 18 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)
... 24 more
问题原因
自签名证书需要添加到信任区,但JVM的证书信任区似乎独立于操作系统,所以需要使用keytool工具导入。
解决步骤
- 下载证书 比如,使用burpsuite抓包,需要将burpsuite的ca证书下载至本地,假设保存为
C:\ca.cer
。 - 导入证书 JVM的keystore默认密码是
changeit
使用administrator身份运行导入命令,比如将C:\ca.cer证书添加到JVM的信任区,并指定别名为burpsuite
。
shell
& 'C:\Program Files\Java\jdk1.8.0_231\bin\keytool.exe' -import -v -trustcacerts -alias burpsuite -file C:\ca.cer -storepass changeit -keystore 'C:\Program Files\Java\jdk1.8.0_231\jre\lib\security\cacerts'
- 验证 方式一: 重新运行Java程序,不会再报SSLHandshakeException;
方式二: 使用keytool的-list
参数;shell& 'C:\Program Files\Java\jdk1.8.0_231\bin\keytool.exe' -list -keystore 'C:\Program Files\Java\jdk1.8.0_231\jre\lib\security\cacerts' | findstr "burp"
清理
当证书使用完想要移除,可使用如下命令:
shell
& 'C:\Program Files\Java\jdk1.8.0_231\bin\keytool.exe' -delete -alias burpsuite -keystore 'C:\Program Files\Java\jdk1.8.0_231\jre\lib\security\cacerts'