我对使用okhttp3库进行https请求的android本机应用程序有问题。我必须使用客户端证书进行身份验证。问题是,当我调用build
的{{1}}函数时,它会抛出HandshakeCertificates.Builder
以获取某些 string 的长度(我不知道它是什么字符串)。我发现,只有在构建之前调用NullPointerException
时才会发生。
我能够调试heldCertificate
,其中使用别名,密钥,密码和链参数调用KeyStore.setKeyEntry
。它们都不是null,我认为它们具有正确的值(但我不是证书的专家,因此可能缺少某些内容)。我无权访问BcKeyStoreSpi.engineSetKeyEntry的代码。
我正在将Android 9 Enterprise与Samsung Galaxy Tab A SM-T515上的工作资料一起使用。
依赖项(仅适用于okhttp):
有人可以帮我吗?谢谢
代码
BcKeyStoreSpi.engineSetKeyEntry
Stacktrace
PrivateKey privateKey = KeyChain.getPrivateKey(context, certAlias);
X509Certificate[] certChain = KeyChain.getCertificateChain(context, certAlias);
X509Certificate mdmCert = certChain[0];
HandshakeCertificates.Builder builder = new HandshakeCertificates.Builder();
builder.addPlatformTrustedCertificates();
for (X509Certificate cert : certChain) {
builder.addTrustedCertificate(cert);
}
builder.heldCertificate( //if this is commented then everything is ok
new HeldCertificate(
new KeyPair(
mdmCert.getPublicKey(),
privateKey
),
mdmCert
),
certChain
);
HandshakeCertificates clientCertificates = builder.build(); //this throws exception
答案 0 :(得分:0)
您无法提取密钥来填充另一个密钥库。相反,您应该使用类似于本文的自定义密钥库。
https://medium.com/@_kbremner/android-and-client-authentication-fd416af19a04
KeyChain.choosePrivateKeyAlias(this,
{ alias -> storeAlias(alias) },
arrayOf("RSA", "DSA"), // List of acceptable key types. null for any
null, // issuer, null for any
null, // host name of server requesting the cert, null if unavailable
443, // port of server requesting the cert, -1 if unavailable
null) // alias to preselect, null if unavailable
关键代码为
val pk = KeyChain.getPrivateKey(applicationContext, alias)!!
val chain = KeyChain.getCertificateChain(applicationContext, alias)!!
val km = object : X509KeyManager {
override fun getClientAliases(keyType: String?, issuers: Array<Principal>): Array<String> {
return arrayOf(alias)
}
override fun chooseClientAlias(keyType: Array<out String>?, issuers: Array<out Principal>?, socket: Socket?): String {
return alias
}
override fun getServerAliases(keyType: String?, issuers: Array<Principal>): Array<String> {
return arrayOf()
}
override fun chooseServerAlias(keyType: String?, issuers: Array<Principal>, socket: Socket): String {
return ""
}
override fun getCertificateChain(alias: String?): Array<X509Certificate> {
return chain
}
override fun getPrivateKey(alias: String?): PrivateKey {
return pk
}
}
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(arrayOf(km), trustManagers, null)
val client: OkHttpClient = OkHttpClient.Builder()
.sslSocketFactory(sslContext.socketFactory, trustManagers[0] as X509TrustManager)
.build()