「javax.net.ssl.SSLHandshakeException:ハンドシェイクに失敗しました」カスタムTrustManagerと証明書ピンニングを追加した後でも

Neeraj sewani

Jamendo APIを使用して音楽をダウンロードする予定ですが、APIに接続すると、次のエラーがスローされました。

javax.net.ssl.SSLHandshakeException: Handshake failed
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:286)
        at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:351)
        at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:310)
        at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:178)
        at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:236)
        at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:109)
        at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:77)
        at okhttp3.internal.connection.Transmitter.newExchange$okhttp(Transmitter.kt:162)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:35)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:82)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:84)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:71)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:184)
        at okhttp3.RealCall.execute(RealCall.kt:66)
        at com.example.musicplayer.utils.CertificatePinningKt.certificatePinning(CertificatePinning.kt:26)
        at com.example.musicplayer.fragments.HomeFragment$onActivityCreated$1$1.invokeSuspend(HomeFragment.kt:42)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
     Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xedb6ee48: Failure in SSL library, usually a protocol error
    error:100000f0:SSL routines:OPENSSL_internal:UNSUPPORTED_PROTOCOL (external/boringssl/src/ssl/handshake_client.cc:576 0xe5faba43:0x00000000)
        at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
        at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:375)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:224)
            ... 27 more

次に、特定のCA証明書がAndroidに認識されていないことを知りました。その方法は、TrustManagerこのSO投稿の承認された回答のように、httpsリクエストで証明書を検証しないようにするか、カスタムTrustManager追加してCA証明書を承認することです。このグーグルドキュメントに従って私が通信する必要があるサーバーの、そして私は後者のアプローチを取りました。

!)まず、次のコマンドを使用してJamendoのサーバー情報を確認しました

$ openssl s_client -connect jamendo.com:443 | openssl x509 -noout -subject -issuer

その結果、

depth = 3 C = US、O = "The Go Daddy Group、Inc。"、OU = Go Daddy Class 2認定機関による返品の確認:
1depth = 2 C = US、ST = Arizona、L = Scottsdale、O = "GoDaddy .com、Inc。 "、CN = Go Daddy Root Certificate Authority-G2 verify return:1
depth = 1 C = US、ST = Arizona、L = Scottsdale、O =" GoDaddy.com、Inc。 "、OU = http: //certs.godaddy.com/repository/、CN = Go Daddy Secure Certificate Authority-G2 verify return:1
depth = 0 C = LU、L = Luxembourg、O = Jamendo SA、CN = .jamendo.com verify return:1
subject = / C = LU / L = Luxembourg / O = Jamendo SA / CN =
.jamendo.com issuer = /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com、Inc./OU= http: //certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority-G2

JamendoGoDaddyのホスティングサービスを使用しているようです。そのため、認証ページに移動しました。上記の出力のように、使用されている証明書はG2グループからのものであるため、出力に記載されているルート証明書中間証明書(最初の2つをダウンロードしました。

2)次に、カスタムSSLSocketFactoryTrustManagerを作成しようとしましたが、同じエラーが発生しました。このアプローチは次のコードに示されています

fun getCACertificateAndroid(resources: Resources): Pair<SSLSocketFactory, X509TrustManager> {
    val cf: CertificateFactory = CertificateFactory.getInstance("X.509")

    //  certificate 1
    var caInput: InputStream = resources.openRawResource(R.raw.gdig2)
    val ca: X509Certificate = caInput.use {
        cf.generateCertificate(it) as X509Certificate
    }
    Log.d("GetCACertificateAndroid", "getCACertificateAndroid: ca= + ${ca.subjectDN}")

    //  certificate 2
    caInput = resources.openRawResource(R.raw.gdroot_g2)
    val ca1: X509Certificate = caInput.use {
        cf.generateCertificate(it) as X509Certificate
    }
    Log.d("GetCACertificateAndroid", "getCACertificateAndroid: ca1= + ${ca1.subjectDN}")

    // Create a KeyStore containing our trusted CAs
    val keyStoreType = KeyStore.getDefaultType()
    val keyStore = KeyStore.getInstance(keyStoreType).apply {
        load(null, null)
        setCertificateEntry("ca", ca)
        setCertificateEntry("ca1", ca1)
    }

    // Create a TrustManager that trusts the CAs inputStream our KeyStore
    val tmfAlgorithm: String = TrustManagerFactory.getDefaultAlgorithm()
    val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm).apply {
        init(keyStore)
    }

    // Create an SSLContext that uses our TrustManager
    val context: SSLContext = SSLContext.getInstance("TLS").apply {
        init(null, tmf.trustManagers, null)
    }


    return Pair(context.socketFactory, tmf.trustManagers[0] as X509TrustManager)
}

他のファイル

...

val (_sslSocketFactory, x509tTrustManager) = getCACertificateAndroid(resources)

    val client = OkHttpClient.Builder()
        .sslSocketFactory(_sslSocketFactory, x509tTrustManager)
        .build()

    val gson = GsonBuilder()
        .setLenient()
        .create()

    val retrofit = Retrofit.Builder()
        .baseUrl("https://api.jamendo.com/v3.0/playlists/?client_id=c7668145&format=jsonpretty&namesearch=cool") //   "https://storage.googleapis.com/"
        .addConverterFactory(GsonConverterFactory.create(gson))
        .client(client)
        .build()

...

3)次にOKHttpでの証明書のピン留め について知り、次のコマンドを実行して、ダウンロードした証明書のbase64エンコーディング取得して試してみようと思いました。

openssl x509 -in cert.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

この投稿の受け入れられた回答に基づいて、次のコードを実行しようとしましたが、それでもエラーは解決しません。

fun certificatePinning() {
    val hostname = "api.jamendo.com/v3.0/playlists/?client_id=c7668145&format=jsonpretty&namesearch=cool"
    val sha256base64_hash1 = "sha256/Ko8tivDrEjiY90yGasP6ZpBU4jwXvHqVvQI0GS3GNdA="
    val sha256base64_hash2 = "sha256/8Rw90Ej3Ttt8RRkrg+WYDS9n7IS03bk5bjP/UXPtaY8="


    val certificatePinner = CertificatePinner.Builder()
        .add(hostname, sha256base64_hash1)
        .add(hostname, sha256base64_hash2)
        .build()
    val client = OkHttpClient.Builder()
        .certificatePinner(certificatePinner)
        .build()

    val request = Request.Builder()
        .url("https://$hostname")
        .build()
    client.newCall(request).execute()
}

誰かが私を正しい方向に向けることができれば、それは大きな助けになるでしょう。

nysos

ハンドシェイク:問題は、新しいプロトコルバージョンをサポートする古い非推奨TLSプロトコルのバージョン(1.0)を使用していないジャメンドのAPIによるものです
* https://github.com/square/okhttp/issues/4670 * https://medium.com/ square-corner-blog / okhttp-3-13-requires-android-5-818bb78d07ce

補足:私は間違いなくカスタムTrustManager実装を選択します。これは、たとえば、エンドポイントが自己署名証明書を使用している場合にのみ意味があります。基本的なチェックとして、電話/エミュレーターブラウザでJamendo URLを直接開いて問題が発生するかどうかを確認することにより、AndroidシステムTrustStoreが機能していることを確認しますか?固定は追加の保護を提供しますが、発生している基本的なハンドシェイクの問題は解決しません。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ