java - 将多个 SSL 证书固定添加到 Android KeyStore 不起作用。 (来自资源文件)

标签 java android ssl x509certificate android-keystore

我想将资源文件中的多个 SSL 证书添加到 Android KeyStore,如下所示:

if (sslContext==null) {
        // loading CA from an InputStream
        InputStream is = AVApplication.getContext().getResources().openRawResource(R.raw.wildcard);
        String certificates = Converter.convertStreamToString(is);
        String certificateArray[] = certificates.split("-----BEGIN CERTIFICATE-----");

        for (int i = 1; i < certificateArray.length; i++) {
            certificateArray[i] = "-----BEGIN CERTIFICATE-----" + certificateArray[i];
            //LogAV.d("cert:" + certificateArray[i]);

            // generate input stream for certificate factory
            InputStream stream = IOUtils.toInputStream(certificateArray[i]);

            // CertificateFactory
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            // certificate
            Certificate ca;
            try {
                ca = cf.generateCertificate(stream);
            } finally {
                is.close();
            }

            // creating a KeyStore containing our trusted CAs
            KeyStore ks = KeyStore.getInstance("BKS");
            ks.load(null, null);
            ks.setCertificateEntry("av-ca" + i, ca);

            // TrustManagerFactory
            String algorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
            // Create a TrustManager that trusts the CAs in our KeyStore
            tmf.init(ks);

            // Create a SSLContext with the certificate that uses tmf (TrustManager)
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
        }

    }

    return sslContext;

只有文件的最后一个证书有效! 证书似乎覆盖了另一个。

文件看起来像:

-----BEGIN CERTIFICATE-----
    cert 
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
    cert 
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
    cert 
-----END CERTIFICATE-----

我希望有人能帮助我! :)

最佳答案

感谢@Dan Getz,现在可以了。

<强>1。使用 SSL 上下文和自签名证书的解决方案:

public static SSLContext getSSLContext() throws Exception {
        if (sslContext==null) {
            // loading CA from an InputStream
            InputStream is = AVApplication.getContext().getResources().openRawResource(R.raw.certificates);
            String certificates = Converter.convertStreamToString(is);
            String certificateArray[] = certificates.split("-----BEGIN CERTIFICATE-----");

            // creating a KeyStore containing our trusted CAs
            KeyStore ks = KeyStore.getInstance("BKS");
            ks.load(null, null);
            for (int i = 1; i < certificateArray.length; i++) {
                certificateArray[i] = "-----BEGIN CERTIFICATE-----" + certificateArray[i];
                //LogAV.d("cert:" + certificateArray[i]);

                // generate input stream for certificate factory
                InputStream stream = IOUtils.toInputStream(certificateArray[i]);

                // CertificateFactory
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                // certificate
                Certificate ca;
                try {
                    ca = cf.generateCertificate(stream);
                } finally {
                    is.close();
                }

                ks.setCertificateEntry("av-ca" + i, ca);
            }
            // TrustManagerFactory
            String algorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
            // Create a TrustManager that trusts the CAs in our KeyStore
            tmf.init(ks);

            // Create a SSLContext with the certificate that uses tmf (TrustManager)
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
        }

        return sslContext;
    }

然后使用 SSL 上下文:

client = okHttpClient.newBuilder()
         .sslSocketFactory(getSslContext(context).getSocketFactory())
         .build();

<强>2。通过指纹使用 OkHttp 固定非根证书的解决方案:

固定一个 根 CA,我正在使用 OkHttp 的 CertificatePinner(!这不适用于自签名证书 - 根 CA):

CertificatePinner = new CertificatePinner.Builder()
            .add(new URL(url).getHost(), "sha256/<certificate1 fingerprint [base64]>")
            .add(new URL(url).getHost(), "sha256/<certificate2 fingerprint [base64]>")
            .build();
OkHttpClient client;
    client = okHttpClient.newBuilder()
        .certificatePinner(certificatePinner)
        .build();

关于java - 将多个 SSL 证书固定添加到 Android KeyStore 不起作用。 (来自资源文件),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35430839/

相关文章:

java - 为什么在实现优先级队列时使用堆而不是二叉树?

java - 如何使用 OpenCloud 在 Java 中生成标签云?

android - 单体机器人 : Running out of space on fresh Virtual Device?

java - Android,setReuseAddress 不起作用

安装为多个图标的 Android 应用 Activity

ssl - 如何在 WildFly 中启用某些密码套件?

java - 单击java JList中的项目时,如何打开新窗口或新框架?

java - 了解 JVM GC

java - 从 Clojure 调用的 App Engine URLFetch 服务给出 AccessControlException

ubuntu - 我的 HTTPS (SSL/TLS) nginx 配置给了我超时