calebisstupid
calebisstupid

Reputation: 433

Android - converting pkcs12 certificate string to x509 certificate object for bks keystore

I am writing an android app that requires SSL certification for certain web requests. Unlike the options I see online about creating the keystore files using the cert file, I have to make an initial web request that returns the certificate as a string in a json response.

The JSON data is formatted like the following... (note: the following certificate is shortened, the "..." does not exist in an actual response)

"result":{
    "pkcs12": "Ulv6GtdFbjzLeqlkelqwewlq822OrEPdH+zxKUkKGX/eN...9801asds3BCfu52dm7JHzPAOqWKaEwIgymlk="
},

I am decoding this value using Base64.deocode to save it as a byte[]

ssl.setPkcs12( Base64.decode( jsonObject.optString( "pkcs12" ) ) );

Then I am trying to create a X509Certificate using the byte[]

CertificateFactory certFactory = CertificateFactory.getInstance( "X.509" );
InputStream in = new ByteArrayInputStream( ssl.getPkcs12() );
X509Certificate cert = (X509Certificate) certFactory.generateCertificate( in );

My code is failing on the generateCertificate() method with

"java.security.cert.CertificateException: org.apache.harmony.security.asn1.ASN1Exception: ASN.1 Sequence: mandatory value is missing at [4]".

I have spent a great deal of time trying to fix what appears to be a simple problem with no luck at all. Any help would be amazing!

Upvotes: 5

Views: 7273

Answers (1)

calebisstupid
calebisstupid

Reputation: 433

In case anyone else needs the answer...

I was able to work around this by completely stripping out the BouncyCastle libraries and using a PKCS12 store instead of a BKS. The following snippet is the solution. I no longer had to generate a certificate object, instead I am saving the json certificate string in the preferences, then grabbing it and using it to generate a keystore on the fly. The base64 decoder is not the BouncyCastle decoder, it is a custom standard decoder.

KeyStore keyStore = KeyStore.getInstance( "PKCS12" );
String pkcs12 = UserSession.getCertificate( context );
InputStream sslInputStream = new ByteArrayInputStream( MyBase64Decoder.decode( pkcs12.getBytes() ) );
keyStore.load( sslInputStream, "password".toCharArray() );

Upvotes: 9

Related Questions