ehmunnehm
ehmunnehm

Reputation: 730

Load SSL certificate from file in Android

I'm trying to load a self signed SSL certificate from a file.

According to this https://developer.android.com/reference/java/security/cert/CertificateFactory it should work like this:

private void LoadCert()
{
    try
    {
        AssetFileDescriptor assetFileDescriptor = this.getAssets().openFd("certbase64.cer");
        FileDescriptor fileDescriptor = assetFileDescriptor.getFileDescriptor();

        FileInputStream fis = new FileInputStream(fileDescriptor);
        BufferedInputStream bis = new BufferedInputStream(fis);

        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        while (bis.available() > 0)
        {
            Certificate cert = cf.generateCertificate(bis);
            System.out.println(cert.toString());
        }
    }
    catch (Exception ex)
    {
        Log.d("Error", ex.getMessage());
    }
}

However I get this error:

D/Error: com.android.org.conscrypt.OpenSSLX509CertificateFactory$ParsingException: com.android.org.conscrypt.OpenSSLX509CertificateFactory$ParsingException: java.lang.RuntimeException: error:0c0000be:ASN.1 encoding routines:OPENSSL_internal:WRONG_TAG

The file:

-----BEGIN CERTIFICATE-----
MIICzjCCAbagAwIBAgIQRYyJrMpTfrlNFpAM8oS1VDANBgkqhkiG9w0BAQsFADAQ
MQ4wDAYDVQQDEwVTZWZmYTAeFw0xOTA2MjUyMDM5MTdaFw0yMDA2MjUwMDAwMDBa
MBAxDjAMBgNVBAMTBVNlZmZhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA+WFZChTqIIqamM0v+EeaZGhxopmkbmbCfL73dhBKZOOPq2ALwGWO9+ABjVDZ
Z5igcmhuYa29BymB9oMeyOWiyD1p/Wo1RUENCf5zTxOXdCCSF/up/ahj3q3M4afV
RNg8/4ld3r3m2u6XbOr2+y3p//9zgmilS5uswefM+p058uxBX4eoeDj7JhCNUuy5
xqWmvJAdaPL3/W/CjDva8c0HQ8GenMmi/JYwtjuZTYcKCk2Oxha5aCn0zu0DiwaY
s5/+x0/iyhg9kMXKjEDDTwu41wL1G90uKN7H+81uf+eEf0qHjwb+SMzugDiWbwcX
NZw4cL2fbi9z3QEy2k9Yov6NGQIDAQABoyQwIjALBgNVHQ8EBAMCBDAwEwYDVR0l
BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBABX/uVlO1dtFXj/bRDEz
S+gAc+5Bl4GggzRA5sxR1+FqS37AxkiHhsBweuxK5bx0wZBykzHhjmq24vnBRmt1
ucfffpJ2rJjlsoya6GEL/qTvj3gxvAH023M+V/Sdvg8K+reX/NGrRsVb19McDjbw
JqGyIDO4f5uOzMmky5zRoo8SbYTFZwPnRTL4oI99C7YWMGWOGPF/HvjqC2D+xRUy
cb8RWtj1ms6uwu96CQgU4i26a7xwVDP4mUAnOc7gdpdtQoDHROvz2LO04unEtfRd
jWO79/7nICA0miHo6QBVVxq5s6JOIyd1J5a2d8p+HZN4fDcEV6vB9VUU67WvjYXy
EIU=
-----END CERTIFICATE-----

Any idea what the problem might be?

Upvotes: 2

Views: 3827

Answers (2)

ehmunnehm
ehmunnehm

Reputation: 730

It seems like the way the file was passed was the problem. Not sure exactly why but it works like this:

InputStream is = getAssets().open("certbase64.cer");
BufferedInputStream bis = new BufferedInputStream(is);
...

Upvotes: 1

solaza
solaza

Reputation: 1291

Not sure if this helps you but still.

sifrbl.SifrBlCert is just full path where file is located,

class TLSSocketFactory extends SSLSocketFactory {

private SSLSocketFactory internalSSLSocketFactory;

public TLSSocketFactory(SifrBl sifrbl) throws Exception  {

    FileInputStream fisTLS = new FileInputStream(sifrbl.SifrBlTls);
    FileInputStream fis = new FileInputStream(sifrbl.SifrBlCert);

    CertificateFactory cf = CertificateFactory.getInstance("X.509");

    Certificate ca;
    try {
        ca = cf.generateCertificate(fisTLS);
    } finally {
        fisTLS.close();
    }

    //Create a KeyStore containing our trusted CAs
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(null, null);
    keyStore.setCertificateEntry("ca", ca);

    KeyStore privatekeyStore = KeyStore.getInstance("PKCS12"); //
    privatekeyStore.load(fis, sifrbl.SifrBlPass.toCharArray());
    Log.i("jm_","KeyStore size: " + keyStore.size());

    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(keyStore);
    Log.i("jm_","TrustManagerFactory size: " + tmf.getTrustManagers().length);

    KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509"); //x509
    kmf.init(privatekeyStore, sifrbl.SifrBlPass.toCharArray());
    Log.i("jm_","KeyManagerFactory size: " + kmf.getKeyManagers().length);


    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");//TLSv1.2
    sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

    internalSSLSocketFactory = sslContext.getSocketFactory();

}

@Override
public String[] getDefaultCipherSuites() {
    return internalSSLSocketFactory.getDefaultCipherSuites();
}

@Override
public String[] getSupportedCipherSuites() {
    return internalSSLSocketFactory.getSupportedCipherSuites();
}

@Override
public Socket createSocket() throws IOException {
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
}

@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}

@Override
public Socket createSocket(String host, int port) throws IOException {
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}

@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}

@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}

@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}

private Socket enableTLSOnSocket(Socket socket) {
    if(socket != null && (socket instanceof SSLSocket)) {
        ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
    }
    return socket;
}

}

I call it like this

TLSSocketFactory socketFactory = new TLSSocketFactory(sifrbl);
HttpsURLConnection urlConnection = null;
urlConnection.setSSLSocketFactory(socketFactory);

Upvotes: 1

Related Questions