Java-如何解码Base64编码的证书

问题描述:

以下是我的要求:

  1. 程序将输入一个带有3个标签的xml文件:和.所有这些数据都是Base64编码的.注意:程序正在使用BC罐子
  2. 程序需要对它们进行解码,并使用签名和证书来验证数据的真实性
  3. 验证后的数据应经过Base64解码,然后写入另一个文件

下面是我的试图对证书进行解码的代码:

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

}

当我打印新String(certByteValue,StandardCharsets.UTF_8)的值时,程序正在打印一些无法识别的文本.当执行代码X509Certificate cert = (X509Certificate)certFactory.generateCertificate(inputStream);的最后一行时,系统抛出java.security.cert.CertificateException:无法解析证书:java.io.IOException:无效的BER/DER数据(太大?).

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.

修改 上面代码的输入流将是一个xml文件.另一个程序使用带有签名和证书的base64编码数据创建该xml文件.在该程序中,使用以下代码来对证书进行编码:

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

变量 encodedStringCert 作为标签内的证书值传递.在此问题顶部共享的程序中,我需要对该证书值进行解码.

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.

样本证书内容:----- BEGIN证书----- MIIDBjCCAe6 .... IM1g == ----- END CERTIFICATE -----

Sample certificate content: -----BEGIN CERTIFICATE----- MIIDBjCCAe6....IM1g== -----END CERTIFICATE-----

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

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

问题可能是源数据不是base64 X509证书,或者是库Base64.decode()的编码问题.我建议对Java> 6

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

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

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

我假设您的证书没有标签----- BEGIN CERTIFICATE ---------- END CERTIFICATE -----

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

已编辑

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

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