在 Java 中以编程方式启用 old/unsafe 密码

Enabling old/unsafe Ciphers programmatically in Java

我目前正在为 REST API 编写包装器。该站点的 SSL 通过 cloudflare 计划。 我正在尝试使用 OkHttp3 调用 api,这里的问题是 cloudflare 显然使用了一些旧密码,默认情况下 Java 已禁用(在 java.security 中)。

当我尝试向 api 发出 POST 请求时,我得到了这个堆栈跟踪:

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:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:241)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:198)
at okhttp3.internal.connection.RealConnection.buildConnection(RealConnection.java:174)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:114)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:193)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:129)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:98)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:109)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:124)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:170)
at okhttp3.RealCall.execute(RealCall.java:60)
at de.dootdoot.dubtrack4k.requesttypes.AbstractRequest.request(AbstractRequest.kt:28)
at de.dootdoot.dubtrack4k.requesttypes.AbstractRequest.request(AbstractRequest.kt:23)
at de.dootdoot.dubtrack4k.HttpRequester.post(HttpRequester.kt:26)
at de.dootdoot.dubtrack4k.HttpRequester.request(HttpRequester.kt:14)
at de.dootdoot.dubtrack4k.HttpRequester.request$default(HttpRequester.kt:11)
at de.dootdoot.dubtrack4k.requests.LoginRequest.setURL(LoginRequest.kt:50)
at de.dootdoot.dubtrack4k.requests.LoginRequest.request(LoginRequest.kt:17)
at de.dootdoot.dubtrack4k.models.Account.login(Account.kt:10)
at de.dootdoot.dubtrack4k.Dubtrack.login(Dubtrack.kt:19)
at LoginTest.loginTest(LoginTest.kt:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:53)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
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:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
... 65 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:146)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 71 more

所以我四处寻找了一下,找到了一种启用 SSL 调试的方法。 这导致了这个调试日志(Hastebin,因为由于某种原因它不会进入代码块):

http://hastebin.com/palomijisa.dos

接近日志的末尾,它是这样说的:

%% Invalidated:  [Session-1, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
main, SEND TLSv1.2 ALERT:  fatal, description = certificate_unknown

这让我 google 多了一些。显然这是一个默认禁用的老式密码套件,我可以确认,它列在 java.security 的禁用算法部分。 现在我正在写一个 API 包装器,在我的机器上编辑它是没有意义的,因为它不允许任何其他人使用它。 所以现在我的问题是,有没有办法只允许包装器所在的会话使用该证书? 我仔细查看了 OkHttp3,确实在他们的 CipherSuite class 中列出了密码套件,但我不知道如何使用它。 有没有人对这种情况有任何经验? 提前致谢!

问题是您的 JVM 不信任 StartCom 作为根 CA,因此证书被拒绝。

证书由

签署

主题:CN=StartCom Class 2 IV 服务器 CA,OU=StartCom 证书颁发机构,O=StartCom Ltd.,C=IL

这是调试日志中的错误

main, SEND TLSv1.2 ALERT:  fatal, description = certificate_unknown

手动下载https://aia.startssl.com/certs/ca.crt一次

您可以将其永久导入此 JVM 实例中。它应该是安全的,因为 chrome 和 OSX 已经支持它。

https://www.ailis.de/~k/uploads/scripts/import-startssl

keytool -keystore C:\Program Files\Java\jdk1.8.0_73\jre\lib\security\cacerts -storepass changeit -import -trustcacerts -alias startcom -file ca.crt

或者将证书与您的程序打包并在运行时加载。这是我建议的路线。

https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java

https://github.com/yschimke/oksocial/blob/master/src/main/java/com/baulsupp/oksocial/security/CertificateUtils.java