Java – generateCertificate() occurs at CertificateException

generateCertificate() occurs at CertificateException… here is a solution to the problem.

generateCertificate() occurs at CertificateException

I’m developing my Android app. I’m trying to generate an X509Certificate instance from my certificate file stream but get CertificateException, here’s my simple code:

import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
...
public class CertMgr {
   my certification file 'mycert.p12' located in my app internal storage
   File certFile = GET_CERT();

X509Certificate cert = null;
   try {

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

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

if(bis.available() > 0){
           I got CertificateException here, see the stack trace
          cert = (X509Certificate) cf.generateCertificate(bis); line nr 150
      }
   }catch(...)
      {...}
 ...
}

Stack trace:

javax.security.cert.CertificateException: org.apache.harmony.security.asn1.ASN1Exception: ASN.1 Sequence: mandatory value is missing at [4]
11-11 17:30:20.731: W/System.err(11529):    at javax.security.cert.X509Certificate.getInstance(X509Certificate.java:94)
11-11 17:30:20.731: W/System.err(11529):    at javax.security.cert.X509Certificate.getInstance(X509Certificate.java:213)
11-11 17:30:20.731: W/System.err(11529):    at com.my.app.CertMgr.getCert(CertMgr.java:150)

Can someone explain to me why this exception is occurring?

P.S.: This is the class I use from the Android SDK X509Certificate , CertificateFactory

If you’re curious about why I’m doing this, the reason is that I want my app to be able to install the certificate (mycert.p12) via the following code (if the code above is working):

Intent installIntent = KeyChain.createInstallIntent();

installIntent.putExtra(KeyChain.EXTRA_CERTIFICATE, cert.getEncoded());
installIntent.putExtra(KeyChain.EXTRA_NAME, MY_CERT);
startActivityForResult(installIntent, INSTALL_KEYCHAIN_CODE);

Solution

You are trying to read the PKCS#12 data structure because it is an X509 certificate. PKCS The #12 standard specifies a data structure that can bundle multiple certificates and private keys, optionally protected with a password.

In order to read PKCS#12 data, you need to load it using KeyStore. This code fragment shows how to list all entries for the PCKS#12 file:

KeyStore keyStore = KeyStore.getInstance("PKCS12");
File p12File = GET_CERT();
FileInputStream fis = new FileInputStream(p12File);
BufferedInputStream bis = new BufferedInputStream(fis);
keyStore.load(bis, password.toCharArray());  password is the PKCS#12 password. If there is no password, just pass null
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
    String alias = aliases.nextElement();
    /* Do something with the keystore entry */
}

A KeyStore entry can be a private key, a chain with or without an associated certificate (that is, a sequence of certificates from the root certificate to the certificate corresponding to the private key), or a trusted certificate. You can determine the entry type through the KeyStore.isKeyEntry and KeyStore.isCertificateEntry methods.

Based on the KeyChain Intent you provided, it seems that you want to add a new trusted root CA certificate to the key chain. So I think you should list the certificate entries for the PKCS#12 file.

Edit (November 12, 2013).

How to get a trusted certificate from keystore:

String alias = aliases.nextElement();
if (keyStore.isCertificateEntry(alias)) { // keep only trusted cert entries
    Certificate caCert = keyStore.getCertificate(alias)
    byte[] extraCertificate = caCert.getEncoded();
    Intent installIntent = KeyChain.createInstallIntent();
    installIntent.putExtra(KeyChain.EXTRA_CERTIFICATE, extraCertificate);
    installIntent.putExtra(KeyChain.EXTRA_NAME, MY_CERT);
    startActivityForResult(installIntent, INSTALL_KEYCHAIN_CODE);
}

Related Problems and Solutions