47
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AndroidでTLS1.2のサーバーにhttps接続したときjavax.net.ssl.SSLProtocolExceptionになって通信できない場合の対処方法

Last updated at Posted at 2015-09-29

iOS9でTLS1.2が必須になったため、APIサーバーのTLSを1.2必須に変更にしたところ、AndroidにてRetrofitとPicassoがjavax.net.ssl.SSLProtocolExceptionを出して通信できなくなってしまい、何とか対応したのでそのメモ。
iOS9対応で今後頻発しそうな気もするので対処方法を残しておきます。

追記:サーバーの設定を変更したところ再びjavax.net.ssl.SSLProtocolExceptionが発生しました、どうやらTLS1.2以外に有効にしてあったTlsVersionで通信ができていた模様。
サーバー側が完全にTLS1.2以外を通さない設定の場合Android 4.3以下の場合サポートされていないため通信できなさそう。

#エラー内容
HTC HTL21 Android 4.1.1(API16)にてエラー。
ASUS Nexus 7 Android 5.1.1 (API22)ではエラーは発生しなかったので古い端末で発生する問題だと思われます。

D/Retrofit: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5d95bcd0: Failure in SSL library, usually a protocol error
D/Retrofit: error:14077102:SSL routines:SSL23_GET_SERVER_HELLO:unsupported protocol (external/openssl/ssl/s23_clnt.c:714 0x5c685bbc:0x00000000)
D/Retrofit:     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:412)
D/Retrofit:     at com.squareup.okhttp.Connection.connectTls(Connection.java:235)
D/Retrofit:     at com.squareup.okhttp.Connection.connectSocket(Connection.java:199)
D/Retrofit:     at com.squareup.okhttp.Connection.connect(Connection.java:172)
D/Retrofit:     at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367)
D/Retrofit:     at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
D/Retrofit:     at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328)
D/Retrofit:     at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245)
D/Retrofit:     at com.squareup.okhttp.Call.getResponse(Call.java:267)

#対処方法
OkHttpClientにTLS1.2を設定したものをそれぞれの通信時に渡してやればいい。
以下はtlsVersionsにTLS1.2を設定したもの。

public static OkHttpClient getFixTlsVersionsClient() {
    OkHttpClient okHttpClient = new OkHttpClient();
    ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
            .tlsVersions(TlsVersion.TLS_1_2)
            .build();
    okHttpClient.setConnectionSpecs(Collections.singletonList(spec));
    return okHttpClient;
}

##Retrofit

String URL = "アクセスしたいURL";
OkHttpClient okHttpClient = getFixTlsVersionsClient();

RestAdapter restAdapter = new RestAdapter.Builder()
        .setClient(new OkClient(okHttpClient))
        .setEndpoint(URL).build();

##Picasso

OkHttpClient okHttpClient = getFixTlsVersionsClient();
Picasso picasso = new Picasso.Builder(context).downloader(new OkHttpDownloader(okHttpClient)).build();
picasso.with(context).load("画像のURL").into(imageView);

以下の方法でグローバルインスタンスに一度定義すれば、毎回呼び出すときに定義する必要がなくなる。

OkHttpClient okHttpClient = getFixTlsVersionsClient();
Picasso picasso = new Picasso.Builder(context).downloader(new OkHttpDownloader(okHttpClient)).build();
Picasso.setSingletonInstance(picasso);

##TLS1.2以外も対応したい
TLS1.1やTLS1.0や(POODLEの問題があったため使われないと思うが)SSL3.0も同時に有効にしたい場合は、TlsVersion.TLS.TLS_1_2の後にTlsVersion.TLS_1_1, TlsVersion.TLS_1_0, TlsVersion.SSL_3_0を追加してやればいい。

public static OkHttpClient getFixTlsVersionsClient() {
    OkHttpClient okHttpClient = new OkHttpClient();
    ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
            .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0, TlsVersion.SSL_3_0)
            .build();
    okHttpClient.setConnectionSpecs(Collections.singletonList(spec));
    return okHttpClient;
}

#参考

47
50
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?