【问题标题】:Attach the SSL client cert okhttp3 . Handshake failed附加 SSL 客户端证书 okhttp3 。握手失败
【发布时间】:2018-05-15 15:06:11
【问题描述】:

我一直在尝试添加与服务器的 SSL 连接,但不幸的是它不起作用 - 仍然得到 javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found..

操作顺序:

  • 应用端创建证书

  • 将创建的证书发送到服务器

  • 在请求中,我们获得了可以使用的证书,例如MIIEpzCCAo+gAwIBAgICALQwDQYJKoZIhvcNAQELBQAwgYAxCzAJBgNVBAYTAlBM[...]6AlW6gjevIU7ZP2lIZWmA9f5uPc3Js1aft3UHmVfdiTaG+rcAVsw+ck7aQ== (ROOT_CA)

  • 接下来的请求将附上此证书 (ROOT_CA)。

负责发送证书的代码:

    private void retrofitConfiguration(Context context){
            OkHttpClient.Builder client = new OkHttpClient.Builder();
            ProviderInstaller.installIfNeeded(context);
            X509Certificate ca = loadCertificate();
            KeyStore keyStore = createKeyStore(ca);
            TrustManager[] trustManagers = createTrustManager(keyStore);
            SSLContext sslContext = null;
            sslContext = createSSLContext(trustManagers, keyStore);
            X509TrustManager _trustManager = (X509TrustManager) trustManagers[0];
            client.sslSocketFactory(sslContext.getSocketFactory(), _trustManager);
            client.hostnameVerifier(getHostnameVerifier());
            buildRetrofit(client.build());
     }

    private X509Certificate loadCertificate() throws CertificateException {
         CertificateFactory cf = CertificateFactory.getInstance("X.509");
         String ca = ROOT_CA;
         byte[] decoded = Base64.decode(ca);
         return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(decoded));
     }

    private KeyStore createKeyStore(X509Certificate ca) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
         String keyStoreType = KeyStore.getDefaultType();
         KeyStore keyStore = KeyStore.getInstance(keyStoreType);
         keyStore.load(null, null);
         keyStore.setCertificateEntry("ca", ca);
         return keyStore;
    }

     private TrustManager[] createTrustManager(KeyStore keyStore) throws NoSuchAlgorithmException, KeyStoreException {
         String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
         TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
         tmf.init(keyStore);
         return tmf.getTrustManagers();
     }

     private SSLContext createSSLContext(TrustManager[] trustManagers, KeyStore keyStore) throws KeyManagementException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException {
         SSLContext sslContext = SSLContext.getInstance("TLS");

         KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
         kmf.init(keyStore, new char[]{0});
         KeyManager[] keyManagers = kmf.getKeyManagers();

         sslContext.init(keyManagers, trustManagers, null);
         return sslContext;
     }


     private HostnameVerifier getHostnameVerifier() {
         return (hostname, session) -> {
             return true;
         };
     }

我尝试使用 https://github.com/rfreedman/android-ssl 中的 CustomTrustManager 得到相同的结果。

我真的不明白为什么它在那个时候不起作用..(经历了很多这样的其他话题)

任何帮助将不胜感激!

更新

现在我正在使用这种方法:

 private SSLSocketFactory getSSLSocketFactory()
        throws CertificateException, KeyStoreException, IOException,
        NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException {

    Certificate clientCA = parseClientCertificate();
    KeyStore clientKeyStore = KeyStore.getInstance("BKS");
    clientKeyStore.load(null, null);
    clientKeyStore.setCertificateEntry("clientCA", clientCA);
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
    keyManagerFactory.init(clientKeyStore, null);
    KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();


    Certificate rootCA = parseRootCertificate();
    KeyStore rootKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    rootKeyStore.load(null, null);
    rootKeyStore.setCertificateEntry("rootCA", rootCA);
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(rootKeyStore);
    TrustManager[] managers = tmf.getTrustManagers();

    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(keyManagers, managers, null);
    return sslContext.getSocketFactory();
}

得到javax.net.ssl.SSLHandshakeException: Handshake failed。此连接到 https,我正在尝试将我的客户端证书附加到请求中。 (使用 okhttp3 和 android 7.1.1 测试)。我在堆栈中浏览了很多主题,但找不到任何可行的解决方案。

完整的堆栈跟踪:

W: javax.net.ssl.SSLHandshakeException: Handshake failed
W:     at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms@11746440:54)
W:     at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:267)
W:     at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:237)
W:     at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:148)
W:     at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:186)
W:     at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
W:     at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
W:     at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:212)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at com.network.ApiClient.lambda$retrofitConfiguration$0(ApiClient.java:127)
W:     at com.network.ApiClient$$Lambda$1.intercept(Unknown Source)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
W:     at okhttp3.RealCall.execute(RealCall.java:63)
W:     at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
W:     at retrofit2.adapter.rxjava.CallExecuteOnSubscribe.call(CallExecuteOnSubscribe.java:40)
W:     at retrofit2.adapter.rxjava.CallExecuteOnSubscribe.call(CallExecuteOnSubscribe.java:24)
W:     at retrofit2.adapter.rxjava.BodyOnSubscribe.call(BodyOnSubscribe.java:33)
W:     at retrofit2.adapter.rxjava.BodyOnSubscribe.call(BodyOnSubscribe.java:25)
W:     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
W:     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
W:     at rx.Observable.unsafeSubscribe(Observable.java:10346)
W:     at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100)
W:     at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:230)
W:     at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
W:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
W:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
W:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
W:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
W:     at java.lang.Thread.run(Thread.java:761)
W: Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7f8f068740: Failure in SSL library, usually a protocol error
W: error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (third_party/openssl/boringssl/src/ssl/tls_record.cc:575 0x7f8f0fb180:0x00000001)
W:     at com.google.android.gms.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
W:     at com.google.android.gms.org.conscrypt.SslWrapper.doHandshake(:com.google.android.gms@11746440:2)
W:     at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms@11746440:19)
W:  ... 43 more
W: com.network.errors.RetrofitException: Handshake failed
W:     at com.network.RxErrorHandlingCallAdapterFactory$RxCallAdapterWrapper.asRetrofitException(RxErrorHandlingCallAdapterFactory.java:93)
W:     at com.network.RxErrorHandlingCallAdapterFactory$RxCallAdapterWrapper.access$000(RxErrorHandlingCallAdapterFactory.java:51)
W:     at com.network.RxErrorHandlingCallAdapterFactory$RxCallAdapterWrapper$1.call(RxErrorHandlingCallAdapterFactory.java:71)
W:     at com.network.RxErrorHandlingCallAdapterFactory$RxCallAdapterWrapper$1.call(RxErrorHandlingCallAdapterFactory.java:68)
W:     at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)
W:     at retrofit2.adapter.rxjava.BodyOnSubscribe$BodySubscriber.onError(BodyOnSubscribe.java:64)
W:     at retrofit2.adapter.rxjava.CallArbiter.emitError(CallArbiter.java:141)
W:     at retrofit2.adapter.rxjava.CallExecuteOnSubscribe.call(CallExecuteOnSubscribe.java:43)
W:     at retrofit2.adapter.rxjava.CallExecuteOnSubscribe.call(CallExecuteOnSubscribe.java:24)
W:     at retrofit2.adapter.rxjava.BodyOnSubscribe.call(BodyOnSubscribe.java:33)
W:     at retrofit2.adapter.rxjava.BodyOnSubscribe.call(BodyOnSubscribe.java:25)
W:     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
W:     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
W:     at rx.Observable.unsafeSubscribe(Observable.java:10346)
W:     at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100)
W:     at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:230)
W:     at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
W:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
W:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
W:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
W:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
W:     at java.lang.Thread.run(Thread.java:761)
W: Caused by: javax.net.ssl.SSLHandshakeException: Handshake failed
W:     at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms@11746440:54)
W:     at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:267)
W:     at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:237)
W:     at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:148)
W:     at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:186)
W:     at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
W:     at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
W:     at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:212)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at com.network.ApiClient.lambda$retrofitConfiguration$0(ApiClient.java:127)
W:     at com.network.ApiClient$$Lambda$1.intercept(Unknown Source)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
W:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
W:     at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
W:     at okhttp3.RealCall.execute(RealCall.java:63)
W:     at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
W:     at retrofit2.adapter.rxjava.CallExecuteOnSubscribe.call(CallExecuteOnSubscribe.java:40)
W:  ... 15 more
W: Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7f8f068740: Failure in SSL library, usually a protocol error
W: error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (third_party/openssl/boringssl/src/ssl/tls_record.cc:575 0x7f8f0fb180:0x00000001)
W:     at com.google.android.gms.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
W:     at com.google.android.gms.org.conscrypt.SslWrapper.doHandshake(:com.google.android.gms@11746440:2)

【问题讨论】:

  • 它看起来像stackoverflow.com/questions/9249158/…,但没有解决方案。客户端证书在本地生成,发送到服务器,由它签名并作为响应返回。但它看起来像 keystore 忽略它并且不发送到服务器。
  • getCertificateChain("clientCA") 返回 null

标签: java android ssl retrofit okhttp


【解决方案1】:

我明白了!

我必须将它添加到我的 KeyStore:

    Certificate[] chain = new Certificate[] {clientCA, rootCA};
    keyStore.setCertificateEntry("clientCA", clientCA);
    keyStore.setCertificateEntry("rootCA", rootCA);
    keyStore.setKeyEntry("keys", getPrivateKey(), password, chain);

【讨论】:

    猜你喜欢
    • 2016-01-18
    • 2016-05-22
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 1970-01-01
    相关资源
    最近更新 更多