Android 无法验证证书签名?
我从这边使用SSL套接字和Trustmanager 但我一直得到以下错误: 09-28 19:52:41.942:WARN/System.err(10101):javax.net.ssl.SSLHandshakeException:org.bounchycastle.jce.exception.ExtCertPathValidatorException:无法验证证书签名 怎么了? 我已经检查了stackoverflow上的不同帖子,但我似乎无法让它正常工作 我的代码:Android 无法验证证书签名?,android,https,x509certificate,Android,Https,X509certificate,我从这边使用SSL套接字和Trustmanager 但我一直得到以下错误: 09-28 19:52:41.942:WARN/System.err(10101):javax.net.ssl.SSLHandshakeException:org.bounchycastle.jce.exception.ExtCertPathValidatorException:无法验证证书签名 怎么了? 我已经检查了stackoverflow上的不同帖子,但我似乎无法让它正常工作 我的代码: SchemeRegistr
SchemeRegistry schemeRegistry = new SchemeRegistry();
// http scheme
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// https scheme
schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
params = new BasicHttpParams();
params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 1);
params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(1));
params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, "utf8");
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope("www.example.com", AuthScope.ANY_PORT),
new UsernamePasswordCredentials("user", "password"));
clientConnectionManager = new ThreadSafeClientConnManager(params, schemeRegistry);
context = new BasicHttpContext();
context.setAttribute("http.auth.credentials-provider", credentialsProvider);
DefaultHttpClient client = new DefaultHttpClient(clientConnectionManager, params);
HttpGet get = new HttpGet("https://www.example.com/web/restricted/form/formelement=512663");
HttpResponse response = client.execute(get, context);
Log.w("Response ","Status line : "+ response.toString());
最有可能的是,服务器返回的证书链具有您不信任的权限。 (意味着:您的设备不知道授权证书是可信的) 解决方案:仔细检查来自HTTPS网站的证书,并将各自的权限添加到您的信任库中-但这部分似乎很棘手 (以下是一些解释:
)正如Michael Levy所提到的,我之所以会遇到这种异常情况,是因为我让Android模拟器打开了几天,而时钟变得非常不同步。一旦我重新启动模拟器,异常就消失了。顺便说一句,我们可以很容易地重新产生这个错误——只需将手机的日期更改为几年后
注意:在不同的手机中,错误可能略有不同。有些可能会显示证书已过期。检查设备的时间,更正它,然后再次检查。更新 我在API 16 emulator上还遇到了另一个错误: 例程:SSL23\u获取\u服务器\u你好:tlsv1警报协议版本 (外部/openssl/ssl/s23\u clnt.c:741' 阅读并更改代码,以便:
val okHttpClient = getOkHttpBuilder().build()
private fun getOkHttpBuilder(): OkHttpClient.Builder {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Security.insertProviderAt(Conscrypt.newProvider(), 1)
}
return OkHttpClient().newBuilder()
}
// build.gradle:
implementation 'org.conscrypt:conscrypt-android:2.5.1'
==旧答案===
在我的例子中,Android 4和5上出现了以下错误:
原因:
com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException:
无法验证证书:证书在5月30日星期六过期
10:48:38 GMT+00:00 2020(与8月13日星期四11:47:00 GMT+00:00相比)
2020年)
原因:java.security.cert.CertificateExpiredException:
证书于5月30日星期六10:48:38 GMT+2020年00:00到期(与
8月13日星期四11:47:00 GMT+00:00 2020)
服务器有证书错误(可能已过期)
有关
改装
的信息,请参阅。如果将燃油
用作REST库,请参阅
您可以信任所有证书,但这很危险
import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.security.cert.CertificateException
companion object {
private val gson: Gson
private val retrofit: Retrofit
init {
val okHttpClient = getOkHttpBuilder().build()
gson = GsonBuilder().setLenient().create()
retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
private fun getOkHttpBuilder(): OkHttpClient.Builder =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
OkHttpClient().newBuilder()
} else {
getUnsafeOkHttpClient()
}
private fun getUnsafeOkHttpClient(): OkHttpClient.Builder =
try {
// Create a trust manager that does not validate certificate chains
val trustAllCerts: Array<TrustManager> = arrayOf(
object : X509TrustManager {
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<X509Certificate?>?,
authType: String?) = Unit
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<X509Certificate?>?,
authType: String?) = Unit
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
}
)
// Install the all-trusting trust manager
val sslContext: SSLContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, SecureRandom())
// Create an ssl socket factory with our all-trusting manager
val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
val builder = OkHttpClient.Builder()
builder.sslSocketFactory(sslSocketFactory,
trustAllCerts[0] as X509TrustManager)
builder.hostnameVerifier { _, _ -> true }
builder
} catch (e: Exception) {
throw RuntimeException(e)
}
}
导入java.security.SecureRandom
导入java.security.cert.x509证书
导入javax.net.ssl*
导入javax.security.cert.CertificateException
伴星{
私人val gson:gson
私人增值税改装:改装
初始化{
val okHttpClient=getOkHttpBuilder().build()
gson=GsonBuilder().setLenient().create()
改装=改装.Builder()
.baseUrl(基本URL)
.客户(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
private fun getOkHttpBuilder():OkHttpClient.Builder=
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.M){
OkHttpClient().newBuilder()
}否则{
getUnsafeOkHttpClient()
}
私有fun getUnsafeOkHttpClient():OkHttpClient.Builder=
试一试{
//创建不验证证书链的信任管理器
val trustAllCerts:Array=arrayOf(
对象:X509TrustManager{
@抛出(CertificateException::类)
重写fun checkClientTrusted(链:数组?,
authType:字符串?=单位
@抛出(CertificateException::类)
覆盖fun checkServerTrusted(链:数组?,
authType:字符串?=单位
重写GetAcceptedAssuers():Array=arrayOf()
}
)
//安装所有信任管理器
val sslContext:sslContext=sslContext.getInstance(“SSL”)
init(null,trustAllCerts,SecureRandom())
//使用我们的全信任管理器创建ssl套接字工厂
val sslSocketFactory:sslSocketFactory=sslContext.socketFactory
val builder=OkHttpClient.builder()
建造商:sslSocketFactory(sslSocketFactory,
trustAllCerts[0]作为X509TrustManager)
builder.hostnameVerifier{{{,{->true}
建设者
}捕获(e:例外){
抛出运行时异常(e)
}
}
另请参见Android版本检查和Glide连接。Hi Konstantin,Thx的回复,但我认为我必须以另一种方式登录此站点,这太复杂了。我要登录的站点有一个登录表单,可以通过HTTP提交,然后登录经过身份验证,并通过SSL重定向到我想要的页面。i t试想一篇HTTP文章,其中保存了来自HTTPGet的Cookie,是否应该这样做?你没有做到这一点-你永远不会得到HTTPS连接。你可以通过提交HTTP表单来成功,但通过SSH重定向将无法工作,除非你对证书问题进行排序-这是你不信任服务器的一方。有趣的是,有些服务器存在缺陷,并且只是无法验证客户端的签名(尤其是JBoss有这个bug)您可能还想检查手机上的日期和时间设置。如果时钟太不同步,您可能会遇到类似的错误。如果您将
Fuel
用作REST库,请参阅。我在没有SIM卡的物理Galaxy Note设备上遇到类似问题。有趣的是,内置浏览器工作正常。一旦我更新了时间同步设置对于自动,我不再遇到任何错误。是的,我面临证书握手的问题,并且发现我的设备时间没有正确设置。它在过去被设置为某些事情,ssl握手失败。我在Android 4和5的Crashlytics上也遇到了完全相同的错误,但我仍然对为什么会发生以及为什么只有在ESE2操作系统。@VGM,谢谢!正如我在mo之后理解的那样
import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.security.cert.CertificateException
companion object {
private val gson: Gson
private val retrofit: Retrofit
init {
val okHttpClient = getOkHttpBuilder().build()
gson = GsonBuilder().setLenient().create()
retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
private fun getOkHttpBuilder(): OkHttpClient.Builder =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
OkHttpClient().newBuilder()
} else {
getUnsafeOkHttpClient()
}
private fun getUnsafeOkHttpClient(): OkHttpClient.Builder =
try {
// Create a trust manager that does not validate certificate chains
val trustAllCerts: Array<TrustManager> = arrayOf(
object : X509TrustManager {
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<X509Certificate?>?,
authType: String?) = Unit
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<X509Certificate?>?,
authType: String?) = Unit
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
}
)
// Install the all-trusting trust manager
val sslContext: SSLContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, SecureRandom())
// Create an ssl socket factory with our all-trusting manager
val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
val builder = OkHttpClient.Builder()
builder.sslSocketFactory(sslSocketFactory,
trustAllCerts[0] as X509TrustManager)
builder.hostnameVerifier { _, _ -> true }
builder
} catch (e: Exception) {
throw RuntimeException(e)
}
}