2017-02-03 1 views
3

クライアントでRetrofitを使用してHTTPSJSONのデータを取得するアプリケーションをビルドしています。 KitKatでうまく動作します。 Android 5,6,7に移行すると、SSLハンドシェイクが失敗します。更新:API21 +デバイスで起動したときにAndroidアプリがSSLハンドシェイクに失敗する

サーバーはTLSv1と他には何をサポートしています。また、期限切れの古い自己署名証明書も使用します。 QualysのSSLツールでテストしたところ、すべてのバージョンのAndroidが接続できるはずだと教えてくれました。

OkHttpクライアントを::

public class HTTPClient { 

public static OkHttpClient getUnsafeOkHttpClient() { 
    try { 
     // Create a trust manager that does not validate certificate chains 

     final TrustManager[] trustAllCerts = new TrustManager[] { 
       new X509TrustManager() { 
        @Override 
        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) { 
        } 

        @Override 
        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { 
        } 

        @Override 
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
         return new java.security.cert.X509Certificate[]{}; 
        } 
       } 
     }; 

     // Install the all-trusting trust manager 
     final SSLContext sslContext = SSLContext.getInstance("TLSv1"); 
     sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); 
     // Create a ssl socket factory with our all-trusting manager 
     final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); 
     //URL url = new URL(ApiIntentService.getHostAddress()); 
     //final SSLSocketFactory sslSocketFactory = new NoSSLv3SocketFactory(url); 

//   ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS) 
//     .tlsVersions(TlsVersion.TLS_1_0) 
//     .cipherSuites(
//       CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 
//       CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 
//       CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 
//       CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 
//       CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 
//       CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 
//       CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 
//       CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 
//       CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA, 
//       CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA) 
//     .build(); 

//   String hostname = "api.server.domain"; 
//   CertificatePinner certificatePinner = new CertificatePinner.Builder() 
//     .add(hostname, "sha256/3Iiwgs3a0qjPCnBQzW/GeHhPbZvhaJtxKvMJJVO5KdU=") 
//     .build(); 

     final OkHttpClient.Builder builder = new OkHttpClient.Builder(); 
//   builder.connectionSpecs(Collections.singletonList(spec)); 
//   builder.certificatePinner(certificatePinner); 
      builder.sslSocketFactory(sslSocketFactory); 
      builder.hostnameVerifier(new HostnameVerifier() { 
       @Override 
       public boolean verify(String hostname, SSLSession session) { 
        return true; 
       } 
      }); 
      builder.authenticator(new Authenticator() { 
       @Override 
       public Request authenticate(Route route, Response response) throws IOException { 
        String credential = Credentials.basic("user", "pass"); 
        return response.request().newBuilder() 
          .header("Authorization", credential) 
          .build(); 
       } 
      }); 
     OkHttpClient okHttpClient = builder.build(); 
     return okHttpClient; 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
} 

私はひどく、このコードは、セキュリティの観点から解体方法を承知していますここで私が持っているものです。私の監督はそれをそうするように要求し、私は彼にその悪いことを知らせました。

私は自分の問題を解決するために2つのことを試みましたが、コードのピースでコメントアウトされています。具体的にはTLSv1を暗号のリストとともに要求しています。他の質問でその2つを見つけましたが、何も変更しませんでした(スタックトレースはまったく同じです)。ここで

スタックトレースは、スタックトレースの興味深いビットです:

I/RETROFIT: Data retrieval failed! javax.net.ssl.SSLHandshakeException: Handshake failed 
*snip* 
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb43eb200: Failure in SSL library, usually a protocol error 
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:770 0xac6fedd4:0x00000000) 
       at  com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 

AndroidはSSLv3突然のすべてを使用しようとしますが、WiresharkのはTLSv1を介して通信を示しているかのように見えます。 Client Helloで始まりますが、サーバーはすぐにHandshake Failure (40)で応答します。

私はすべてのアイデアのうち、だので、すべてのヘルプは大幅に、appreaciatedされます。それが必要な場合は、明確に尋ねてください。

ありがとうございます。

+0

を、あなたははい、私が持っている代わりにConnectionSpec.COMPATIBLE_TLS' –

+0

'の' ConnectionSpec.MODERN_TLS'と 'コメントアウトConnectionSpec'ピースを試してみました。それはもともとそこにあった、私はそれをドキュメントを読んで変更しました。しかし、効果はありません。 –

答えて

2

は、あなたのHTTPクライアントが致命的に安全でないHTTPSサーバに接続できない上司を教えてください。それはコンピュータの限界だと言うことができ、唯一のオプションはサーバーを更新することです。あなたは、開発のみのデバッグモードを追加できることをやったら

。これを行うには、サーバーがサポートする暗号スイートを有効にします。 Qualysツールからリストを取得できます。私にとって

+0

RPiでホストされたテストサーバー(TLSv1.2を使用)で動作し、Androidのバージョンが異なる複数のデバイスでテストされています。明らかにアプリ側の問題ではありません。ご回答いただきありがとうございます。 –

1

ソリューションはOkHttpClientのための許容可能なように、より暗号を追加しました。 API 21以降、一部のTLS証明書はAndroid用に推奨されていません。これは役立つかもしれない:詳細情報については

ConnectionSpec spec = new 
ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) 
      .tlsVersions(TlsVersion.TLS_1_2) 
      .cipherSuites(  
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,      
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) 
      .build(); 

OkHttpClient client = new OkHttpClient.Builder() 
     .connectionSpecs(Collections.singletonList(spec)) 
     .build(); 

をご覧ください。https://github.com/square/okhttp/wiki/HTTPS

+0

私のために働かなかった。 –

+0

私が覚えている限り、私はたくさんの異なる暗号を追加しようとしましたが、うまくいかないでしょう。サーバーソフトウェアを更新することが道でした。 –

関連する問題