当前位置: 首页 > 知识库问答 >
问题:

带有客户端证书的Android okhttp3错误

卫兴邦
2023-03-14
    null

有人能帮帮我吗?谢谢。

代码

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

斯塔克特莱斯

java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:354)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
    at java.util.concurrent.FutureTask.run(FutureTask.java:271)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
    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:764)
 Caused by: java.security.KeyStoreException: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
    at com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi.engineSetKeyEntry(BcKeyStoreSpi.java:685)
    at java.security.KeyStore.setKeyEntry(KeyStore.java:1179)
    at okhttp3.tls.internal.TlsUtil.newKeyManager(TlsUtil.kt:85)
    at okhttp3.tls.HandshakeCertificates$Builder.build(HandshakeCertificates.kt:144)
    at cz.kctdata.skoenergo.ui.activity.MainActivity$GetCertAsyncTask.doInBackground(MainActivity.java:121)
    at cz.kctdata.skoenergo.ui.activity.MainActivity$GetCertAsyncTask.doInBackground(MainActivity.java:85)
    at android.os.AsyncTask$2.call(AsyncTask.java:333)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
    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:764) 

共有1个答案

司徒钱青
2023-03-14

不能提取密钥以填充另一个密钥存储区。相反,您应该使用与本文类似的自定义密钥库。

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()
 类似资料:
  • 问题内容: 使用Websphere MQ 8.x,我们是较大环境中的一个应用程序,并且是某些数据接口的客户端。我们的应用程序是在WildFly 9上运行的Java EE应用程序,该应用程序使用资源适配器()与EAR文件一起部署在同一AS中。我们在两个方向上与MQ服务器进行交互。因此,一方面,我们有一些MDB(由于历史渊源仍是EJB 2.x格式而没有注释)列出了一些队列,并由包含激活配置属性的部署描

  • 我想使用.Net 4.8下的Windows证书存储中的证书建立GRPC SslCredentials()。此链接非常类似,但不提供有效的解决方案。 https://github.com/grpc/grpc/issues/8978 我使用类似于以下内容的代码。ExportToPEM() 是将证书转换为 PEM 格式的自行尝试,但它不起作用。我希望GRPC的C#包装器能够使这变得容易。

  • 问题内容: 我正在尝试确保通过Internet进行通信的Java客户端/服务器应用程序的连接安全。我的想法是将SSL套接字与自签名证书和客户端身份验证一起使用。我做了以下事情: 服务器:包含新的自签名证书的密钥库。 客户端:包含新的自签名证书的密钥库。 服务器:包含导出的客户端证书的信任库(来自上面的项目符号)。导出客户端证书并将其导入服务器的信任库 客户端:包含导出的服务器证书的信任库(从第一个

  • 问题内容: 我还很陌生,对于使用证书进行身份验证时客户端应该显示的内容有些困惑。 我正在编写一个Java客户端,该客户端需要对POST特定对象进行简单的数据处理URL。那部分工作正常,唯一的问题是应该完成。该部分相当容易处理(无论是使用Java的内置HTTPS支持还是使用Java的内置支持),但是我一直坚持使用客户端证书进行身份验证。我注意到这里已经存在一个非常类似的问题,我还没有尝试使用我的代码

  • 我不熟悉SSL和证书。我一直在做关于客户端证书认证的研究。我看过这个和wiki。 因此,如果我必须为我的B2B REST服务实现客户端证书身份验证解决方案,我应该执行以下操作 要求客户端生成自己的私钥,并为其公钥生成证书(CA 颁发?)。通过电子邮件或 USB 闪存盘发送该证书。 在服务器端将客户端的公共证书导入信任存储区并启用客户端身份验证 在握手期间,客户端会出示其证书并进行身份验证,因为服务

  • 本文向大家介绍什么是客户端证书?相关面试题,主要包含被问及什么是客户端证书?时的应答技巧和注意事项,需要的朋友参考一下 客户端系统向远程服务器发出经过身份验证的请求所用的数字证书被称为客户端证书。客户端证书在许多相互认证设计中起着非常重要的作用,为请求者的身份提供了强有力的保证。