Any good example for working with UNKNOWN CA signed certificate(like pkcs12) in android

心已入冬 提交于 2019-12-06 18:05:16

问题


I am working on android application, which requires to communicate with server over ssl. Any good example to work with pkcs12 certificates in android using HttpsUrlConnection


回答1:


After doing some modifications to the code posted by @EpicPandaForce, i was able to successfully run the code.

Changes:

1. KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");

to

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");

to get rid of exception: java.security.NoSuchAlgorithmException: X509 KeyManagerFactory not available

2. KeyStore keyStore = KeyStore.getInstance("PKCS12", BouncyCastleProvider.PROVIDER_NAME); //spongyCastle library

to

KeyStore keyStore = KeyStore.getInstance("PKCS12");

and added the provider to Security Class as shown below

Security.addProvider(new BouncyCastleProvider());

to get rid of Exception:java.security.NoSuchProviderException: no such provider: SC

Then Final complete code:

Security.addProvider(new BouncyCastleProvider());
    SSLContext sslContext = SSLContext.getInstance("TLS");
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init((KeyStore)null); //this is where you would add the truststore
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
    KeyStore keyStore = KeyStore.getInstance("PKCS12"); //spongyCastle library
    keyStore.load(new FileInputStream("D:\\Documents\\VISA Direct Api\\cabcentralcert.p12"), "cabcentral".toCharArray()); //inputStream to PKCS12
    keyManagerFactory.init(keyStore, "cabcentral".toCharArray());
    //TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
    TrustManager[] trustAllCertManagers = { new X509TrustManager() { // this is vulnerable to MITM attack
        @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 new X509Certificate[0];
        }
    }};

    sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCertManagers, new SecureRandom());
    URL url = new URL(strUrl);
    HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) url.openConnection();
    httpsUrlConnection.setSSLSocketFactory(sslContext.getSocketFactory());

    System.out.println("Response Code : " + httpsUrlConnection.getResponseCode());
    System.out.println("Cipher Suite : " + httpsUrlConnection.getCipherSuite());



回答2:


Indeed, although it's a bit messy.

        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init((KeyStore)null); //this is where you would add the truststore
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
        KeyStore keyStore = KeyStore.getInstance("PKCS12", BouncyCastleProvider.PROVIDER_NAME); //spongyCastle library
        keyStore.load(keyStoreStream, keyStorePassword); //inputStream to PKCS12
        keyManagerFactory.init(keyStore, keyStorePassword);
        //TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        TrustManager[] trustAllCertManagers = { new X509TrustManager() { // this is vulnerable to MITM attack
            @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 new X509Certificate[0];
            }
        }};

        sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCertManagers, new SecureRandom());
        URL url = new URL(urlString);
        HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) url.openConnection();
        httpsUrlConnection.setSSLSocketFactory(sslContext.getSocketFactory());

You need the following dependencies:

compile 'com.madgag.spongycastle:core:1.51.0.0'
compile 'com.madgag.spongycastle:prov:1.51.0.0'
compile 'com.madgag.spongycastle:pkix:1.51.0.0'

This needs a bit of fixing though as even though it initializes the key store (that stores the client certificate in PKCS12), it trusts every certificate rather than use a keystore to find out whether it is a trusted certificate or not (and this is vulnerable to Man-in-the-Middle attacks).

EDIT: In order to make SpongyCastle work, you need to add a custom application like this:

import org.spongycastle.jce.provider.BouncyCastleProvider;

public class CustomApplication
        extends Application {
    static {
        Security.insertProviderAt(new BouncyCastleProvider(), 1);
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }
}

And in AndroidManifest.xml:

<application
    android:allowBackup="true"
    android:name=".CustomApplication"


来源:https://stackoverflow.com/questions/30083229/any-good-example-for-working-with-unknown-ca-signed-certificatelike-pkcs12-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!