如何解码 base64 编码的证书

How to decode a base64 encoded certificate

以下是我的要求:

  1. 程序将有一个 XML 文件作为输入,其中包含 3 个标签:OrgContentSignatureCertificate。所有这些数据都是 Base64 编码的。注意:程序正在使用 BC jars
  2. 程序需要解码它们并使用签名和证书验证数据的真实性
  3. 验证后的数据应该进行Base64解码并写入另一个文件

下面是我尝试解码证书的代码:

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

当我打印 new String(certByteValue,StandardCharsets.UTF_8) 的值时,程序正在打印一些无法识别的文本。当执行代码的最后一行时 X509Certificate cert = (X509Certificate)certFactory.generateCertificate(inputStream); 系统抛出

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

由于我是这些证书的新手,所以我陷入了僵局。我无法继续执行该要求。我想知道如何实现我的上述要求。

上述代码的输入流将是一个 XML 文件。另一个程序使用带签名和证书的 base64 编码数据创建 XML 文件。在该程序中,为了对证书进行编码,使用了以下代码:

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 作为标签内的证书值传递。在这个问题顶部分享的程序中,我需要解码这个证书值。

示例证书内容:

-----BEGIN CERTIFICATE-----
MIIDBjCCAe6....IM1g==
-----END CERTIFICATE-----

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

已编辑

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

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