0

I have problem while generating certificate. Following is related code.

@SuppressLint("SdCardPath")
public HttpsURLConnection setUpHttpsConnection(String urlString)
{
    try
    {
        CertificateFactory cf = CertificateFactory.getInstance("X.509","BC");

        AssetManager assManager = context.getAssets();
        InputStream caInput = assManager.open("testCert.pfx");

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

        Certificate ca = cf.generateCertificate(caInput);

        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());

        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);

        URL url = new URL(urlString);
        HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
        urlConnection.setSSLSocketFactory(context.getSocketFactory());

        return urlConnection;
    }
    catch (Exception ex)
    {
        Log.e("fff", "Failed to establish SSL connection to server: " + ex.toString());
        ex.printStackTrace();
        return null;
    }

}

Program gives an error at following line.

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

Error trace ;

com.android.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory$ExCertificateException
rer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
 at com.android.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory.engineGenerateCertificate(CertificateFactory.java:220)
 at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:196)
 at com.example.hilalinan.cert.ServiceCall.setUpHttpsConnection(ServiceCall.java:125)
 at com.example.hilalinan.cert.ServiceCall.doInBackground(ServiceCall.java:58)
 at android.os.AsyncTask$2.call(AsyncTask.java:295)
 at java.util.concurrent.FutureTask.run(FutureTask.java:237)
 at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
 at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalArgumentException: unknown object in getInstance: com.android.org.bouncycastle.asn1.ASN1Integer
 at com.android.org.bouncycastle.asn1.ASN1Sequence.getInstance(ASN1Sequence.java:98)
 at com.android.org.bouncycastle.asn1.x509.TBSCertificate.getInstance(TBSCertificate.java:64)
 at com.android.org.bouncycastle.asn1.x509.Certificate.<init>(Certificate.java:61)
 at com.android.org.bouncycastle.asn1.x509.Certificate.getInstance(Certificate.java:45)
 at com.android.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory.readDERCertificate(CertificateFactory.java:68)
 at com.android.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory.engineGenerateCertificate(CertificateFactory.java:215)
... 9 more

When I searched this issue I found this question in stackoverflow. I understood that my phone does not have BC provider in trusted credentials. OP of the question suggested that I add BC provider to my phone. But even though I install, how can I provide other users install that who are using my program. Also when I googled it how to add BC to my list I couldnt find anything useful.

Is there any idea how to solve my issue?

Thanks in advance.

Community
  • 1
  • 1
Hilal
  • 902
  • 2
  • 22
  • 47
  • 2
    A `pfx` file is a PKCS#12 file which may contain multiple certificates and keys. Therefore you have to load it directly as PKCS12 keystore and not try to generate a certificate object from it! – Robert Sep 20 '16 at 12:23
  • I couldnt understand I am not so familiar with this topic. Could you be more specific? If I cant generate certificate how can I access https service? Should I use `crt` file? – Hilal Sep 20 '16 at 12:40

1 Answers1

2

A pfx file is a PKCS#12 file which may contain multiple certificates and keys (unless you changed the file extension).

The code you use expects a simple certificate (.cer, .crt or .der) file.

Therefore you have to load it directly as PKCS12 keystore and not try to generate a certificate object from it:

InputStream caInput = assManager.open("testCert.pfx");
String pfxPassword = "password"; // change it to the correct password
keyStore.load(caInput, pfxpassword.toCharArray());
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
Robert
  • 39,162
  • 17
  • 99
  • 152
  • Thanks it avoid that problem. But now I am getting another exception. javax.net.ssl.SSLPeerUnverifiedException: Hostname 10.0.0.35 not verified – Hilal Sep 20 '16 at 13:01
  • Looks like the certificate you use on the webserver does not contain the correct hostname (in this case "10.0.0.35"). There is a possibility to disable the hostname validation in Android, however that makes your app vulnerable to attacks. Better to re-create the certificate of the webserver with correct hostname. – Robert Sep 20 '16 at 13:15
  • Thank you so much! Right, certificate may not have correct hostname. Hope it will fix after we correct it. Thanks again – Hilal Sep 20 '16 at 13:20
  • Hi @Robert, Can you Please help me out this "https://stackoverflow.com/questions/51518028/certificate-throwing-exception-com-android-org-bouncycastle-jcajce-provider-asym" – sid Jul 25 '18 at 11:48