Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to decode a base64 encoded certificate

Below is my requirement:

  1. Program will have an XML file as input with 3 tags: OrgContent, Signature and Certificate. All these data are Base64 encoded. Note: Program is using BC jars
  2. Program needs to decode them and verify the data for its authenticity using the signature and certificate
  3. Verified data should be Base64 decoded and written into another file

Below is my code which tries to decode the certificate:

public void executeTask(InputStream arg0, OutputStream arg1) throws SomeException{
    try{
        BufferedReader br = null;
        br = new BufferedReader(new InputStreamReader(arg0));
        String orgContent  = "", splitData = "", signContent = "", certContent = "";
            
        DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
        Document doc = docBuilder.parse(arg0);
        doc.getDocumentElement().normalize();
            
        NodeList originalContent = doc.getElementsByTagName("OrgContent");
        Element originalElement = (Element)originalContent.item(0);
        NodeList textOrgContent = originalElement.getChildNodes();
        orgContent = ((Node)textOrgContent.item(0)).getNodeValue().trim();
            
        NodeList signature = doc.getElementsByTagName("Signature");
        Element signatureElement = (Element)signature.item(0);
        NodeList signatureContent = signatureElement.getChildNodes();
        signContent = ((Node)signatureContent.item(0)).getNodeValue().trim();
            
        NodeList certificate = doc.getElementsByTagName("Certificate");
        Element certificateElement = (Element)certificate.item(0);
        NodeList certificateContent = certificateElement.getChildNodes();
        certContent = ((Node)certificateContent.item(0)).getNodeValue().trim();
        String decodedCertContent = new String(Base64.decode(certContent),StandardCharsets.UTF_8);
        byte[] certByteValue = Base64.decode(certContent);
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        System.out.println("certContent:\n" + new String(certByteValue,StandardCharsets.UTF_8));
        InputStream inputStream = new ByteArrayInputStream(Base64.decode(certContent));
            
        X509Certificate cert = (X509Certificate)certFactory.generateCertificate(inputStream);
        
        arg1.write(decodedOrgData.getBytes());
        arg1.flush();   
    }
    catch (ParserConfigurationException e){
        e.printStackTrace();
    }
    catch (IOException e){
        e.printStackTrace();
    }
    catch (org.xml.sax.SAXException e){
        e.printStackTrace();
    }
    catch (CertificateException e){
        e.printStackTrace();
    }
}

When I print the value of new String(certByteValue,StandardCharsets.UTF_8) the program is printing some unrecognizable text. When executing the last line of the code X509Certificate cert = (X509Certificate)certFactory.generateCertificate(inputStream); system is throwing

java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: Invalid BER/DER data (too huge?).

Since I am a newbie to these certificates thing, I have hit a deadlock. I am unable to proceed with the requirement. I would like to know how to achieve my above said requirements.

The input stream to the above code will be an XML file. Another program creates that XML file with base64 encoded data with signature and certificate. In that program, for encoding the certificate the below code is used:

KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("Filepath/certificate.p12"), "password".toCharArray());
PrivateKey privateKey = (PrivateKey)keyStore.getKey(alias, "password".toCharArray());

CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate) factory.generateCertificate(new FileInputStream("D:/Sujai/Implementation Team/PI/Axis Treds/Certificates/PI_7.5_Cert/Arteria_Certificate-cert.cert"));
byte[] encodedCert = certificate.getEncoded();
String encodedStringCert = new String(Base64.encode(new String(encodedCert).getBytes(StandardCharsets.UTF_8)));

The variable encodedStringCert is passed as the certificate value inside a tag. In the program shared at the top of this question, I need to decode this certificate value.

Sample certificate content:

-----BEGIN CERTIFICATE-----
MIIDBjCCAe6....IM1g==
-----END CERTIFICATE-----
like image 746
Sujaikareik Avatar asked Jan 03 '17 10:01

Sujaikareik


People also ask

How do I decode a Base64 encoded file?

To decode a file with contents that are base64 encoded, you simply provide the path of the file with the --decode flag. As with encoding files, the output will be a very long string of the original file. You may want to output stdout directly to a file.

Can Base64 encoding be decoded?

In JavaScript there are two functions respectively for decoding and encoding Base64 strings: btoa() : creates a Base64-encoded ASCII string from a "string" of binary data ("btoa" should be read as "binary to ASCII"). atob() : decodes a Base64-encoded string("atob" should be read as "ASCII to binary").

What is Base64 certificate?

Base64 is the industry standard format for SSL certificate content. The most common web servers will generate a certificate signing requests as well as accept SSL certificates in base-64 format. The size of the certificate content will depend on the encryption strength of the certificate.

How can I tell if a certificate is Base64 encoded?

To determine if a certificate file is base64 or DER binary, open the file in Notepad. If the text "Begin Certificate" appears at the beginning of the file, it is in base64 format. If "Begin Certificate" does not appear at the beginning of the file, it is in DER binary format.


1 Answers

new String(certByteValue,StandardCharsets.UTF_8) fails because the certificate encoded data is not representable as string

The problem could be that the source data is not a base64 X509 certificate, or a encoding issue with your library Base64.decode(). I suggest use the standard decoder of java 8 Base64.getDecoder().decode() or DataTypeConverter.parseBase64Binary() for java >6

Check also this working code to decode a base64 encoded certificate

String certB64 = "MIIHFDCCBfygAwIBAgIIK2o4sL7KHQgwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTYxMjE1MTQwNDE1WhcNMTcwMzA5MTMzNTAwWjBmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEVMBMGA1UEAwwMKi5nb29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG1y99TYpFSSiawnjJKYI8hyEzJ4M+IELfLjmSsYI7fW/V8AT61quCswtBMikJYqzYBZrV2Reu5sHlLr6936cR6OCBKwwggSoMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjCCA2sGA1UdEQSCA2IwggNeggwqLmdvb2dsZS5jb22CDSouYW5kcm9pZC5jb22CFiouYXBwZW5naW5lLmdvb2dsZS5jb22CEiouY2xvdWQuZ29vZ2xlLmNvbYIWKi5nb29nbGUtYW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xlLmNsgg4qLmdvb2dsZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNvLnVrgg8qLmdvb2dsZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUuY29tLmJygg8qLmdvb2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29nbGUuY29tLnRygg8qLmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2dsZS5lc4ILKi5nb29nbGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5nb29nbGUubmyCCyouZ29vZ2xlLnBsggsqLmdvb2dsZS5wdIISKi5nb29nbGVhZGFwaXMuY29tgg8qLmdvb2dsZWFwaXMuY26CFCouZ29vZ2xlY29tbWVyY2UuY29tghEqLmdvb2dsZXZpZGVvLmNvbYIMKi5nc3RhdGljLmNugg0qLmdzdGF0aWMuY29tggoqLmd2dDEuY29tggoqLmd2dDIuY29tghQqLm1ldHJpYy5nc3RhdGljLmNvbYIMKi51cmNoaW4uY29tghAqLnVybC5nb29nbGUuY29tghYqLnlvdXR1YmUtbm9jb29raWUuY29tgg0qLnlvdXR1YmUuY29tghYqLnlvdXR1YmVlZHVjYXRpb24uY29tggsqLnl0aW1nLmNvbYIaYW5kcm9pZC5jbGllbnRzLmdvb2dsZS5jb22CC2FuZHJvaWQuY29tghtkZXZlbG9wZXIuYW5kcm9pZC5nb29nbGUuY26CBGcuY2+CBmdvby5nbIIUZ29vZ2xlLWFuYWx5dGljcy5jb22CCmdvb2dsZS5jb22CEmdvb2dsZWNvbW1lcmNlLmNvbYIKdXJjaGluLmNvbYIKd3d3Lmdvby5nbIIIeW91dHUuYmWCC3lvdXR1YmUuY29tghR5b3V0dWJlZWR1Y2F0aW9uLmNvbTALBgNVHQ8EBAMCB4AwaAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBThPf/3oDfxFM/hdOi5kLv8qrZbsjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMCEGA1UdIAQaMBgwDAYKKwYBBAHWeQIFATAIBgZngQwBAgIwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5nb29nbGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAWZQy0Kvn9cPnIh7Z4kfUCXX/dhdvjLJYFAn3b3d5DVs1BLYuukfIjilVdAeTUHZH7TLn/uVejg3yS0ssRg1ds1iv2O9DJbnl5FHcjNAvwfN533FulWP41OC6B6dC6BGGTXTvQobDup7/EKg1GWX9ksBtTfKLH5wrjhN955Itnd25Sjw2bSjLaWEtTrjINXmnBoc2+qHFzF/fNxK1KbmkBboUIGoaGsThe3AF0Ye+XAeaZH08+GdrorknlHDQLLtHIcJ3C6PrQ/kTpwWd/TVXW42BN+N7xZiGJbvKOg0S0rk2hzhgX4QoUKZHMqqh1sS6ypkfnWx75nh325y4Tenk+A==";
byte encodedCert[] = Base64.getDecoder().decode(certB64);
ByteArrayInputStream inputStream  =  new ByteArrayInputStream(encodedCert);

CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(inputStream);

I assume that your certificate does not have the tags ----- BEGIN CERTIFICATE ----- and ----- END CERTIFICATE -----

EDITED

You can load directly a .cer file encoded in base64 PEM (with -----BEGIN CERTIFICATE----- tags).

FileInputStream inputStream  =  new FileInputStream (pathToYourCert);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(inputStream);
like image 113
pedrofb Avatar answered Oct 05 '22 04:10

pedrofb