带有客户端证书(crt,p12)的 OkHttp:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚
Posted
技术标签:
【中文标题】带有客户端证书(crt,p12)的 OkHttp:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚【英文标题】:OkHttp with Client Certificate (crt, p12): java.security.cert.CertPathValidatorException: Trust anchor for certification path not found 【发布时间】:2019-10-09 20:36:58 【问题描述】:我正在尝试使用 OKHttp 和 Retrofit 2 发出请求。此请求应通过发送证书来完成(它必须是 p12 或 crt)。我们尝试了不同的方法,但没有人让我成功。我正在使用 badssl.com 进行测试,它允许我向以下 URL 提出请求:https://client.badssl.com,并提供您可以在此处找到的证书:https://badssl.com/download/
我尝试将 p12 和 crt 包含在 assets 文件夹和项目的 raw 文件夹中,并创建了 Keystore、SSLSocketFactory 和 TrustManager。 由于这不起作用,我还尝试创建一个可以发出任何请求的不安全 OkHttpClient,但我没有成功。 在这两种情况下,我都有: “javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚”
public static SSLContext getSSLConfig(Context context) throws CertificateException, IOException,
KeyStoreException, NoSuchAlgorithmException, KeyManagementException
// Loading CAs from an InputStream
CertificateFactory cf = null;
cf = CertificateFactory.getInstance("X.509");
Certificate ca;
// I'm using Java7. If you used Java6 close it manually with finally.
try (InputStream cert = context.getResources().openRawResource(R.raw.somecert))
ca = cf.generateCertificate(cert);
// Creating a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Creating a TrustManager that trusts the CAs in our KeyStore.
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Creating an SSLSocketFactory that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
return sslContext;
val client: OkHttpClient = OkHttpClient.Builder()
.sslSocketFactory(SSLConfigUtils.getSSLConfig(MyClass.getContext()).socketFactory)
.hostnameVerifier _, _ -> true
.build()
val retrofit = Retrofit.Builder()
.addCallAdapterFactory(
RxJava2CallAdapterFactory.create())
.addConverterFactory(
GsonConverterFactory.create(gson))
.baseUrl("https://client.badssl.com/")
.client(client)
.build()
我希望正确地提出改造请求,但每个请求都会返回此错误:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms@17122040@17.1.22 (100700-245988633):43)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:319)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:283)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:168)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
at okhttp3.RealCall.execute(RealCall.java:92)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:186)
at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:656)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:615)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:505)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:424)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:352)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:89)
at java.lang.reflect.Method.invoke(Native Method)
at com.google.android.gms.org.conscrypt.Platform.checkTrusted(:com.google.android.gms@17122040@17.1.22 (100700-245988633):2)
2019-05-23 11:37:15.389 5640-5640/it.sogetel.agtcs E/Errore: at com.google.android.gms.org.conscrypt.Platform.checkServerTrusted(:com.google.android.gms@17122040@17.1.22 (100700-245988633):1)
at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(:com.google.android.gms@17122040@17.1.22 (100700-245988633):12)
at com.google.android.gms.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.google.android.gms.org.conscrypt.NativeSsl.doHandshake(:com.google.android.gms@17122040@17.1.22 (100700-245988633):7)
at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms@17122040@17.1.22 (100700-245988633):14)
... 33 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
... 47 more
【问题讨论】:
请查看this 【参考方案1】:在 OkHttp 中有一个 test case 用于配置客户端身份验证。它可能需要作为一个有用的示例,但您应该注意它在内存中生成证书,而不是从文件中加载它们。
相关代码在okhttp-tls模块中。
另请注意,您的 TrustManager 必须包含服务器的证书,或签署它的证书颁发机构根证书之一。
【讨论】:
以上是关于带有客户端证书(crt,p12)的 OkHttp:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚的主要内容,如果未能解决你的问题,请参考以下文章
OpenSSL 1.0.0生成p12jkscrt等格式证书的命令个过程
如何发送 iOS - 带有 P12 证书的 APN 通知 - C# 示例