从 XAdES-X-L 中获取证书

发布时间 2023-08-25 16:32:00作者: zno2

 

import java.io.ByteArrayInputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import xades4j.properties.CertificateValuesProperty;
import xades4j.properties.QualifyingProperty;

public class XAdESXLUtil {

    public static List<X509Certificate> getCerts(Document xadesxlDoc) {
        if (xadesxlDoc == null) {
            return null;
        }
        NodeList nodeList = xadesxlDoc.getElementsByTagNameNS(QualifyingProperty.XADES_XMLNS,
                CertificateValuesProperty.PROP_NAME);
        if (nodeList.getLength() != 1) {
            return null;
        }
        CertificateFactory cf = null;
        try {
            cf = CertificateFactory.getInstance("X.509", "BC");
        } catch (Exception e1) {
            e1.printStackTrace();
            return null;
        }
        List<X509Certificate> certList = new ArrayList<X509Certificate>();
        Node certificateValues = nodeList.item(0);
        NodeList encapsulatedX509Certificates = certificateValues.getChildNodes();
        for (int i = 0; i < encapsulatedX509Certificates.getLength(); i++) {
            Node item = encapsulatedX509Certificates.item(i);
            String textContent = item.getTextContent();
            ByteArrayInputStream bis = new ByteArrayInputStream(
                    ("-----BEGIN CERTIFICATE-----\r\n" + textContent + "\r\n-----END CERTIFICATE-----").getBytes());
            X509Certificate c;
            try {
                c = (X509Certificate) cf.generateCertificate(bis);
                certList.add(c);
            } catch (CertificateException e) {
                e.printStackTrace();
            }
        }
        return certList;
    }

}

 

关键点:

If the certificate is provided in Base64 encoding, it must be bounded at the beginning by -----BEGIN CERTIFICATE-----, and must be bounded at the end by -----END CERTIFICATE-----. 
Open Declaration Certificate java.security.cert.CertificateFactory.generateCertificate(InputStream inStream) throws CertificateException


Generates a certificate object and initializes it with the data read from the input stream inStream. 

In order to take advantage of the specialized certificate format supported by this certificate factory, the returned certificate object can be typecast to the corresponding certificate class. For example, if this certificate factory implements X.509 certificates, the returned certificate object can be typecast to the X509Certificate class. 

In the case of a certificate factory for X.509 certificates, the certificate provided in inStream must be DER-encoded and may be supplied in binary or printable (Base64) encoding. If the certificate is provided in Base64 encoding, it must be bounded at the beginning by -----BEGIN CERTIFICATE-----, and must be bounded at the end by -----END CERTIFICATE-----. 

Note that if the given input stream does not support mark and reset, this method will consume the entire input stream. Otherwise, each call to this method consumes one certificate and the read position of the input stream is positioned to the next available byte after the inherent end-of-certificate marker. If the data in the input stream does not contain an inherent end-of-certificate marker (other than EOF) and there is trailing data after the certificate is parsed, a CertificateException is thrown.

Parameters:
inStream an input stream with the certificate data.
Returns:
a certificate object initialized with the data from the input stream.
Throws:
CertificateException - on parsing errors.

 

证书例子:

<xades:EncapsulatedX509Certificate>MIIFxDCCBKygAwIBAgIKEOFSkgAAAAGSxDANBgkqhkiG9w0BAQUFADCB2zELMAkGA1UEBhMCSVIx
FTATBgNVBAoTDEdvdmVybm1lbnRhbDEvMC0GA1UECxMmSXJhbiBDZW50ZXIgZm9yIGUtQ29tbWVy
Y2UgRGV2ZWxvcG1lbnQxOjA4BgNVBAsTMURlcHV0eSBvZiBQS0kgYW5kIENvbW1lcmNpYWwgSW5m
b3JtYXRpb24gU2VjdXJpdHkxIDAeBgNVBAsTF0dlbmVyYWwgSW50ZXJtZWRpYXRlIENBMSYwJAYD
VQQDEx1HSUNBIERpZ2l0YWwgU2lnbiBTaWx2ZXIgTm8uNTAeFw0xNzAxMTgwNzUzNDJaFw0xODAx
MTgwNzUzNDJaMIHOMQswCQYDVQQGEwJJUjETMBEGA1UECAwK2KrZh9ix2KfZhjETMBEGA1UEBwwK
2KrZh9ix2KfZhjEVMBMGA1UEChMMVW5hZmZpbGlhdGVkMSQwIgYDVQQLExtJbmRpdmlkdWFsIExl
dmVsIDIgKFNpbHZlcikxEzARBgNVBAUTCjEyOTI4Mjg5NTExETAPBgNVBCoMCNmF2K3ZhdivMRUw
EwYDVQQEDAzZhdmH2LHYstin2K8xGTAXBgNVBAMTEE1vaGFtbWFkIE1laHJ6YWQwgZ8wDQYJKoZI
hvcNAQEBBQADgY0AMIGJAoGBAK0rP1xKkSQ4XhtA+TrYnmRS3Qp/8YVYG2dV3HQD8pq5aAxmeWb2
gZwCLOCpv/orut8fNOzbUh4MRWCPmEjMJTUTc0XO67bsw2PLQPm9TavN/HQWeAjZVgBHeoHSzf/0
sC/yWaCqLEiPQz1ST7o9v5ZrUZ8Ht4W4lIHhaev/+rbLAgMBAAGjggIXMIICEzAOBgNVHQ8BAf8E
BAMCBsAwHQYDVR0OBBYEFCWKnRlu22wlOCwVGyJl7wtBuyKYMCsGA1UdJQQkMCIGCisGAQQBgjcU
AgIGCisGAQQBgjcKAwwGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFDeoHLs9mut/wKPAN2sWO6e8BqHZ
MEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwuZ2ljYS5pci9yZXBvc2l0b3J5L0RTL0RTLVNp
bHZlci1Oby41LmNybDA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdp
Y2EuaXIvb2NzcDCB3gYDVR0gBIHWMIHTMEUGCWCCbGUBAQECAjA4MDYGCCsGAQUFBwIBFipodHRw
Oi8vd3d3LmdpY2EuaXIvcmVwb3NpdG9yeS9jcHMtZ2ljYS5wZGYwRQYJYIJsZQEBAwICMDgwNgYI
KwYBBQUHAgEWKmh0dHA6Ly93d3cuZ2ljYS5pci9yZXBvc2l0b3J5L2Nwcy1naWNhLnBkZjBDBgdg
gmxlAQMBMDgwNgYIKwYBBQUHAgEWKmh0dHA6Ly93d3cuZ2ljYS5pci9yZXBvc2l0b3J5L2Nwcy1n
aWNhLnBkZjA3BgkrBgEEAYI3FQoEKjAoMAwGCisGAQQBgjcUAgIwDAYKKwYBBAGCNwoDDDAKBggr
BgEFBQcDAjANBgkqhkiG9w0BAQUFAAOCAQEANke02azEjpxHBPRNfhO85rKbe7JDdJla33iNW9pA
5ar0GFFAtsw/0bNv4abHf7AxVpBiSwzMxA/y2UzDUabKd/adwnvG5FyzPM5FwCHEmZ1ZNa2IREs7
zvJnPsaAAygIqyvEWdJsylHqT3G5zUqV5eAvXS3qgjYGEYb+5/0G3bUH5jsjGCQzhhw2enfOYYm3
9D6SBWrgm5OGSyCo2/8SuTJzapqxHvQjhuRcrKkhRYtOmqGiAkPSTj1fY/jB/sN+O3shVo5QBddi
si6oVoERRP/04uoh+tTCRdfd9EwGwuZWk2YydthzhZDOcvwdf4RMlRq7bCpZDMwAJkuAJeusXA==</xades:EncapsulatedX509Certificate>