我正在开发一个Android应用,该应用需要与Artik 055s模块和Samsung处理器进行通信。
Artik创建自己的热点,当时只能将一台设备连接到WiFi。从现在开始,我们应该使用Retrofit使用简单的HTTPS请求/响应。
尝试调用它,我得到一个
javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚。
阅读Android文档后,可能有多种原因。据我对Artik开发人员的了解,处理器中有一个内置的Samsung证书。所以我想知道是否可能有一个自签名证书。然后,Artik上的开发人员抓住了使用WireShark发送的证书并将其发送给我,因此我可以将其合并到应用程序中,然后使用该证书来验证握手。
然后我尝试在https://developer.android.com/training/articles/security-ssl#SelfSigned
的帮助下实现此代码val instrumentDataSource: IInstrumentDataSource
by lazy {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BuildConfig.BASE_URL)
.client(getUnsafeOkHttpClient())
.build()
retrofit.create(IInstrumentDataSource::class.java)
}
private fun getUnsafeOkHttpClient(): OkHttpClient {
try {
// Install the all-trusting trust manager
val sslContext = getSSLContextFromCertificate()
// Create an ssl socket factory with our all-trusting manager
val sslSocketFactory = sslContext.socketFactory
val okHttpClient = OkHttpClient()
return okHttpClient.newBuilder()
.sslSocketFactory(sslSocketFactory)
.hostnameVerifier { hostname, session -> true }
.build()
} catch (e: Exception) {
throw RuntimeException(e)
}
}
private fun getSSLContextFromCertificate(): SSLContext {
val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
val caInput: InputStream = HealthApplication.appContext.resources.openRawResource(R.raw.cert_name)
val ca: X509Certificate = caInput.use {
cf.generateCertificate(it) as X509Certificate
}
System.out.println("ca=" + ca.subjectDN)
// Create a KeyStore containing our trusted CAs
val keyStoreType = KeyStore.getDefaultType()
val keyStore = KeyStore.getInstance(keyStoreType).apply {
load(null, null)
setCertificateEntry("ca", ca)
}
// 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
return SSLContext.getInstance("TLS").apply {
init(null, tmf.trustManagers, null)
}
}
但是我仍然得到和以前完全一样的错误。
如果我尝试使Internet浮动的示例(Android甚至在我刚刚发布的链接中提到),则一切都很好,您可以完全禁用所有检查,例如:
private fun getUnsafeOkHttpClient(): OkHttpClient {
try {
// Create a trust manager that does not validate certificate chains
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
@Throws(CertificateException::class)
override fun checkClientTrusted(
chain: Array<X509Certificate>,
authType: String) {
}
@Throws(CertificateException::class)
override fun checkServerTrusted(
chain: Array<X509Certificate>,
authType: String) {
}
})
// Install the all-trusting trust manager
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustAllCerts,
java.security.SecureRandom())
// Create an ssl socket factory with our all-trusting manager
val sslSocketFactory = sslContext
.socketFactory
val okHttpClient = OkHttpClient()
return okHttpClient.newBuilder()
.sslSocketFactory(sslSocketFactory)
.hostnameVerifier { hostname, session -> true }
.build()
} catch (e: Exception) {
throw RuntimeException(e)
}
}
有人有什么好主意可以继续吗?我知道后一种支票对于生产来说并不安全,但是如果我能正常使用的话,上面的支票是否足够安全?