SSLHandshakeException 但仅限于 Android 12?
SSLHandshakeException but only on Android 12?
我有一个已发布多年的应用程序。它工作得很好,但现在它开始抛出 SLLHandshakeExceptions 但仅适用于 Android 12.
我找不到任何官方文档是否在 Android 12 中发生了一些变化,我必须实施才能使事情正常进行,所以我只是一无所知。
这是日志:
Caused by java.security.cert.CertificateException: Unacceptable certificate: CN=R3, O=Let's Encrypt, C=US
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:609)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:505)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:425)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:353)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:90)
at com.android.org.conscrypt.ConscryptEngineSocket.checkServerTrusted(ConscryptEngineSocket.java:163)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:255)
at com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain(ConscryptEngine.java:1638)
at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(NativeCrypto.java)
at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:569)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:858)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.access0(ConscryptEngineSocket.java:731)
at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:241)
at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:220)
at com.squareup.okhttp.Connection.connectTls(Connection.java:235)
at com.squareup.okhttp.Connection.connectSocket(Connection.java:199)
at com.squareup.okhttp.Connection.connect(Connection.java:172)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367)
at com.squareup.okhttp.OkHttpClient.connectAndSetOwner(OkHttpClient.java:128)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245)
at com.squareup.okhttp.Call.getResponse(Call.java:267)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:224)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:195)
at com.squareup.okhttp.Call.execute(Call.java:79)
at com.kwindoo.application.network.newapilib.lib.BaseNetworkTask.doInBackground(BaseNetworkTask.java:325)
at com.kwindoo.application.network.newapilib.lib.BaseNetworkTask.doInBackground(BaseNetworkTask.java:38)
at android.os.AsyncTask.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:305)
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:920)
我还有第二个异常,即 CertExpiredException。所以这只是服务器端修复?
Caused by java.security.cert.CertificateExpiredException: Certificate expired at Wed Sep 29 12:21:40 PDT 2021 (compared to Thu Mar 31 07:13:28 PDT 2022)
at com.android.org.conscrypt.OpenSSLX509Certificate.checkValidity(OpenSSLX509Certificate.java:269)
at com.android.org.conscrypt.OpenSSLX509Certificate.checkValidity(OpenSSLX509Certificate.java:255)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:605)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:505)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:425)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:353)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:90)
at com.android.org.conscrypt.ConscryptEngineSocket.checkServerTrusted(ConscryptEngineSocket.java:163)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:255)
at com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain(ConscryptEngine.java:1638)
at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(NativeCrypto.java)
at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:569)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:858)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.access0(ConscryptEngineSocket.java:731)
at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:241)
at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:220)
at com.squareup.okhttp.Connection.connectTls(Connection.java:235)
at com.squareup.okhttp.Connection.connectSocket(Connection.java:199)
at com.squareup.okhttp.Connection.connect(Connection.java:172)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367)
at com.squareup.okhttp.OkHttpClient.connectAndSetOwner(OkHttpClient.java:128)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245)
at com.squareup.okhttp.Call.getResponse(Call.java:267)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:224)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:195)
at com.squareup.okhttp.Call.execute(Call.java:79)
at com.kwindoo.application.network.newapilib.lib.BaseNetworkTask.doInBackground(BaseNetworkTask.java:325)
at com.kwindoo.application.network.newapilib.lib.BaseNetworkTask.doInBackground(BaseNetworkTask.java:38)
at android.os.AsyncTask.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:305)
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:920)
我将以下库用于我的网络层:
implementation 'com.squareup.okio:okio:2.8.0'
implementation 'com.squareup.okhttp:okhttp:2.5.0'
有什么建议吗?
第二个例外的到期日期是 let's encrypt 之前使用的 R3 中间签名证书的到期日期:https://docs.certifytheweb.com/docs/kb/kb-202109-letsencrypt/
此后被新的根证书取代,Android 12 与新的根证书兼容。
可能是库的问题,您使用的okhttp版本已经过时:https://square.github.io/okhttp/
您可以尝试迁移到最新版本:
implementation("com.squareup.okhttp3:okhttp:4.9.3")
这是一个 known issue,因为 Let's Encrypt 签署的某些证书不受信任。
这是一个 server-side 问题,请更新证书。
如果您愿意,可以跳过证书检查
创建以下 kotlin class
object RetrofitClientInstance {
fun unSafeOkHttpClient(): OkHttpClient.Builder {
val okHttpClient = OkHttpClient.Builder()
try {
// Create a trust manager that does not validate certificate chains
val trustAllCerts: Array<TrustManager> = arrayOf(object : X509TrustManager {
override fun checkClientTrusted(
chain: Array<out X509Certificate>?,
authType: String?
) {
}
override fun checkServerTrusted(
chain: Array<out X509Certificate>?,
authType: String?
) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
})
// Install the all-trusting trust manager
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, SecureRandom())
// Create an ssl socket factory with our all-trusting manager
val sslSocketFactory = sslContext.socketFactory
if (trustAllCerts.isNotEmpty() && trustAllCerts.first() is X509TrustManager) {
okHttpClient.sslSocketFactory(
sslSocketFactory,
trustAllCerts.first() as X509TrustManager
)
okHttpClient.hostnameVerifier { _, _ -> true }
}
return okHttpClient
} catch (e: Exception) {
return okHttpClient
}
}
}
你可以在 kotlin 中使用它
Retrofit.Builder()
.client(RetrofitClientInstance.unSafeOkHttpClient().build())
并在 java
Retrofit.Builder()
.client(RetrofitClientInstance.INSTANCE.unSafeOkHttpClient().build())
我有一个已发布多年的应用程序。它工作得很好,但现在它开始抛出 SLLHandshakeExceptions 但仅适用于 Android 12.
我找不到任何官方文档是否在 Android 12 中发生了一些变化,我必须实施才能使事情正常进行,所以我只是一无所知。
这是日志:
Caused by java.security.cert.CertificateException: Unacceptable certificate: CN=R3, O=Let's Encrypt, C=US
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:609)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:505)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:425)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:353)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:90)
at com.android.org.conscrypt.ConscryptEngineSocket.checkServerTrusted(ConscryptEngineSocket.java:163)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:255)
at com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain(ConscryptEngine.java:1638)
at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(NativeCrypto.java)
at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:569)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:858)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.access0(ConscryptEngineSocket.java:731)
at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:241)
at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:220)
at com.squareup.okhttp.Connection.connectTls(Connection.java:235)
at com.squareup.okhttp.Connection.connectSocket(Connection.java:199)
at com.squareup.okhttp.Connection.connect(Connection.java:172)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367)
at com.squareup.okhttp.OkHttpClient.connectAndSetOwner(OkHttpClient.java:128)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245)
at com.squareup.okhttp.Call.getResponse(Call.java:267)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:224)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:195)
at com.squareup.okhttp.Call.execute(Call.java:79)
at com.kwindoo.application.network.newapilib.lib.BaseNetworkTask.doInBackground(BaseNetworkTask.java:325)
at com.kwindoo.application.network.newapilib.lib.BaseNetworkTask.doInBackground(BaseNetworkTask.java:38)
at android.os.AsyncTask.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:305)
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:920)
我还有第二个异常,即 CertExpiredException。所以这只是服务器端修复?
Caused by java.security.cert.CertificateExpiredException: Certificate expired at Wed Sep 29 12:21:40 PDT 2021 (compared to Thu Mar 31 07:13:28 PDT 2022)
at com.android.org.conscrypt.OpenSSLX509Certificate.checkValidity(OpenSSLX509Certificate.java:269)
at com.android.org.conscrypt.OpenSSLX509Certificate.checkValidity(OpenSSLX509Certificate.java:255)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:605)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:505)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:425)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:353)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:90)
at com.android.org.conscrypt.ConscryptEngineSocket.checkServerTrusted(ConscryptEngineSocket.java:163)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:255)
at com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain(ConscryptEngine.java:1638)
at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(NativeCrypto.java)
at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:569)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095)
at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:858)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.access0(ConscryptEngineSocket.java:731)
at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:241)
at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:220)
at com.squareup.okhttp.Connection.connectTls(Connection.java:235)
at com.squareup.okhttp.Connection.connectSocket(Connection.java:199)
at com.squareup.okhttp.Connection.connect(Connection.java:172)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367)
at com.squareup.okhttp.OkHttpClient.connectAndSetOwner(OkHttpClient.java:128)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245)
at com.squareup.okhttp.Call.getResponse(Call.java:267)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:224)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:195)
at com.squareup.okhttp.Call.execute(Call.java:79)
at com.kwindoo.application.network.newapilib.lib.BaseNetworkTask.doInBackground(BaseNetworkTask.java:325)
at com.kwindoo.application.network.newapilib.lib.BaseNetworkTask.doInBackground(BaseNetworkTask.java:38)
at android.os.AsyncTask.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:305)
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:920)
我将以下库用于我的网络层:
implementation 'com.squareup.okio:okio:2.8.0'
implementation 'com.squareup.okhttp:okhttp:2.5.0'
有什么建议吗?
第二个例外的到期日期是 let's encrypt 之前使用的 R3 中间签名证书的到期日期:https://docs.certifytheweb.com/docs/kb/kb-202109-letsencrypt/
此后被新的根证书取代,Android 12 与新的根证书兼容。
可能是库的问题,您使用的okhttp版本已经过时:https://square.github.io/okhttp/
您可以尝试迁移到最新版本:
implementation("com.squareup.okhttp3:okhttp:4.9.3")
这是一个 known issue,因为 Let's Encrypt 签署的某些证书不受信任。
这是一个 server-side 问题,请更新证书。
如果您愿意,可以跳过证书检查
创建以下 kotlin class
object RetrofitClientInstance {
fun unSafeOkHttpClient(): OkHttpClient.Builder {
val okHttpClient = OkHttpClient.Builder()
try {
// Create a trust manager that does not validate certificate chains
val trustAllCerts: Array<TrustManager> = arrayOf(object : X509TrustManager {
override fun checkClientTrusted(
chain: Array<out X509Certificate>?,
authType: String?
) {
}
override fun checkServerTrusted(
chain: Array<out X509Certificate>?,
authType: String?
) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
})
// Install the all-trusting trust manager
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, SecureRandom())
// Create an ssl socket factory with our all-trusting manager
val sslSocketFactory = sslContext.socketFactory
if (trustAllCerts.isNotEmpty() && trustAllCerts.first() is X509TrustManager) {
okHttpClient.sslSocketFactory(
sslSocketFactory,
trustAllCerts.first() as X509TrustManager
)
okHttpClient.hostnameVerifier { _, _ -> true }
}
return okHttpClient
} catch (e: Exception) {
return okHttpClient
}
}
}
你可以在 kotlin 中使用它
Retrofit.Builder()
.client(RetrofitClientInstance.unSafeOkHttpClient().build())
并在 java
Retrofit.Builder()
.client(RetrofitClientInstance.INSTANCE.unSafeOkHttpClient().build())