gpt4 book ai didi

android - 找不到证书路径的信任 anchor 。在 Android 上使用自签名客户端证书

转载 作者:行者123 更新时间:2023-12-04 22:35:49 26 4
gpt4 key购买 nike

我有一个简单的 web api 运行在树莓派上,它位于同一个 pi 上的 nginx 服务器后面。我正在使用自签名客户端证书来验证来自 Android 应用程序的调用。这在过去工作得很好,但我最近在重建一些硬件后回到了这个项目,当我尝试在运行 Android 8.1 的 Pixel 2 上使用它时,它出现以下异常:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:219)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:268)
...

我根据以下内容生成了证书和 key :http://nategood.com/client-side-certificate-authentication-in-ngi

使用 curl 进行测试工作正常。

我为应用程序创建了 keystore 以用于:

openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12

我按照以下文章在 Android 中设置客户端证书并连接到服务器:http://chariotsolutions.com/blog/post/https-with-client-certificates-on/

但我使用 OkHttp 在 Kotlin 中重写了它:

private const val SERVER = "https://my.server"

/**
* trustManagers is used to authorize the server's self-signed cert
*/
private val trustManagers by lazy {
val cert = CertificateFactory.getInstance("X.509")
.generateCertificate(appCtx.assets.open("ca.crt")) as X509Certificate

val trustStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply {
load(null, null)
setCertificateEntry(cert.subjectX500Principal.name, cert)
}

TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).apply {
init(trustStore)
}.trustManagers
}

/**
* keyManagers is used to load the client-authentication cert
*/
private val keyManagers by lazy {
// assuming this can only be called after Application is created

val keyStore = KeyStore.getInstance("PKCS12").apply {
load(appCtx.assets.open("client.p12"), "".toCharArray())
}

KeyManagerFactory.getInstance("X509").apply {
init(keyStore, "".toCharArray())
}.keyManagers
}

/**
* sslContext for opening TLS connection to server
*/
private val sslContext by lazy {
SSLContext.getInstance("TLS").apply {
init(keyManagers, trustManagers, null)
}
}

/**
* pass an HTTPS request to server
*/
suspend fun request(url: String): ByteArray? {
return try {
val request = Request.Builder()
.url(url)
.build()
val client = OkHttpClient.Builder()
.sslSocketFactory(sslContext.socketFactory, trustManagers[0] as X509TrustManager)
.build()
client.newCall(request).await().body().byteStream().readBytes()
} catch (e: Exception) {
err(e) { "failed to send request" }
null
}
}

使用 可以工作,但现在不行了。我花了一天半的时间寻找答案,并尝试了以下方法:

  • 我试过使用 HttpURLConnection 而不是 OkHttp
  • 我已经尝试从头开始重新创建所有证书/ key 。
  • 我尝试过使用新的“网络安全配置”:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<!-- Additionally trust user added CAs -->
<certificates src="user" />
<certificates src="@raw/ca"/>
</trust-anchors>
</base-config>
</network-security-config>

我已经阅读了我能找到的关于创建自定义信任管理器的所有示例,它们几乎都是一样的,甚至 https://developer.android.com/training/articles/security-ssl.html#UnknownCa

我尝试过的所有操作都会产生相同的异常,我是否遗漏了什么?

最佳答案

这就是我如何使用 GoDaddy 上的自签名证书让它在我的项目中工作:

  1. 在您的项目中,在 Android Studio 中创建一个名为“raw”(无单引号)的新目录
  2. 在原始文件夹中创建一个新的文本文件,名称任意,扩展名为 .crt (IE gdCert.crt)
  3. 在 GoDaddy cPanel 的“安全”下,单击“SSL/TLS”。单击“证书”下的链接,然后它会显示您已经创建的证书。单击“编辑”链接。选择并复制证书的内容并将其粘贴到您在 Android Studio“原始”文件夹中创建的文本文件中并保存。
  4. 在 Android Studio 中,右键单击“res”文件夹,新建 > XML > App Actions XML 文件。将此文件命名为“network_security_config”(无单引号)
  5. 将以下内容添加到“network_security_config.xml”文件中:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<debug-overrides>
<trust-anchors>
<certificates src="user"/>
<certificates src="@raw/gdcert"/>
</trust-anchors>
</debug-overrides>
</network-security-config>

  1. 在您的 AndroidManifest.xml 文件中,在

android:networkSecurityConfig="@xml/network_security_config"

  1. 在您的解决方案中使用以下 java 代码:

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
SSLSocketFactory ssf = sc.getSocketFactory();
SSLSocket sslsocket = (SSLSocket) ssf.createSocket("yourwebsitename.com", 443);

后跟您尝试运行以连接到服务器的任何代码。

  1. 请注意,第二行调用了一个新方法,该方法应添加到您的类中:

TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

}

@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}};

保存您的项目并运行它。

关于android - 找不到证书路径的信任 anchor 。在 Android 上使用自签名客户端证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48979679/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com