Java - How to decode a Base64 encoded Certificate

时间:2017-01-03 10:23:18

标签: certificate base64 decoding

Below is my requirement:

  1. Program will have an xml file as input with 3 tags: , and . 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.

Edit 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-----

1 个答案:

答案 0 :(得分:9)

new String(certByteValue,StandardCharsets.UTF_8)失败,因为证书编码数据不能表示为字符串

问题可能是源数据不是base64 X509证书,也不是库Base64.decode()的编码问题。我建议使用java 8 Base64.getDecoder().decode()DataTypeConverter.parseBase64Binary()的标准解码器for java> 6

还检查此工作代码以解码base64编码的证书

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);

我认为您的证书没有标记----- BEGIN CERTIFICATE ---------- END CERTIFICATE -----

<强> EDITED

您可以直接加载base64 PEM中编码的.cer文件(带有-----BEGIN CERTIFICATE-----标记)。

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