Как проверить подписанный документ Xades с нулевой ссылкой URI - PullRequest
0 голосов
/ 06 мая 2019

У меня есть документ XML, подписанный XaDes. Документ подписи имеет две ссылки с URI и одну с нулевым URI. Когда я проверяю подпись, я получаю ошибку исключения ссылки NULL.

Исключение в потоке "main" javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: не удалось найти распознаватель для URI NULL и Base NULL

Вот мой подписанный XML

<Sgntr>
   <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <ds:SignedInfo>
         <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
         <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
         <ds:Reference URI="#_d36d665d-470b-429b-921c-f9381d2fc5f9">
            <ds:Transforms>
               <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>IybO1FjRmQn3IbvTrmrxCr1VqUw=</ds:DigestValue>
         </ds:Reference>
         <ds:Reference Type="http://uri.etsi.org/01903/v1.3.2#SignedProperties" URI="#_a4646550-596c-4174-a2c0-2a0118fa1b0e-signedprops">
            <ds:Transforms>
               <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>eI+YLruTZe3qcPs8blatyKvJxZc=</ds:DigestValue>
         </ds:Reference>
         <ds:Reference>  // -----> without URI
            <ds:Transforms>
               <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>k/bzxTU4+icrc+nSaR3WJi6VNEI=</ds:DigestValue>
         </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>
      ............
      </ds:SignatureValue>
      <ds:KeyInfo Id="_d36d665d-470b-429b-921c-f9381d2fc5f9">
        ........
      </ds:KeyInfo>
      <ds:Object>
        .........
      </ds:Object>
   </ds:Signature>
</Sgntr>

Вот мой проверочный код Java

public static void main(String[] args) throws Exception {

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse(new FileInputStream("signedxmlJavaDoc.xml")); // Signed xml with xades

        XPath xpath = XPathFactory.newInstance().newXPath();
        String xpathExpression = "//*[local-name()='Signature']";
        NodeList nodes = (NodeList) xpath.evaluate(xpathExpression, doc.getDocumentElement(), XPathConstants.NODESET);
        if (nodes == null || nodes.getLength() == 0) {
            throw new Exception("Signature is missing in the document");
        }
        Node nodeSignature = nodes.item(0);

        CertificateDetails certDetails = CertificateUtil.getCertificateDetails("keystore.jks", "pass"); // signed jks also for verification

        final KeySelector mockKeySelector = new KeySelector() {

            @Override
            public KeySelectorResult select(KeyInfo keyInfo, Purpose purpose, AlgorithmMethod method, XMLCryptoContext context) throws KeySelectorException {

                return new KeySelectorResult() {
                    @Override
                    public Key getKey() {
                        return certDetails.getX509Certificate().getPublicKey();
                    }
                };
            }
        };

        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
        DOMValidateContext valContext = new DOMValidateContext(mockKeySelector, nodeSignature);

        final NodeList docNodes = doc.getElementsByTagName("Document:Document");
        final Node docNode = docNodes.item(0);

        ByteArrayOutputStream refOutputStream = new ByteArrayOutputStream();
        Transformer xform = TransformerFactory.newInstance().newTransformer();
        xform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        xform.transform(new DOMSource(docNode), new StreamResult(refOutputStream));
        InputStream refInputStream = new ByteArrayInputStream(refOutputStream.toByteArray());
        DOMSignContext dsc = new DOMSignContext(certDetails.getX509Certificate().getPublicKey(), doc.getDocumentElement()); //added ----------
        dsc.putNamespacePrefix(XMLSignature.XMLNS, "ds"); //  ---------added
        dsc.setURIDereferencer(new NoUriDereferencer(refInputStream));

        NodeList nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");
        if (nl.getLength() == 0) {
            throw new Exception("Signature is missing in signature");
        }
        Element elemSignedProps = (Element) nl.item(0);
        valContext.setIdAttributeNS(elemSignedProps, null, "Id");

        XMLSignature signature = fac.unmarshalXMLSignature(valContext);
        boolean coreValidity = signature.validate(valContext);
        if (coreValidity) {
            // signature verified
            System.out.println("signature verified");
        } else {
            // signature verification failed
            System.out.println("Signature failed core validation");
            boolean sv = signature.getSignatureValue().validate(valContext);
            System.out.println("signature validation status: " + sv);
            // check the validation status of each Reference
            Iterator i = signature.getSignedInfo().getReferences().iterator();
            for (int j = 0; i.hasNext(); j++) {
                final Reference ref = (Reference) i.next();
                final String refURI = ref.getURI();
                boolean refValid = ref.validate(valContext);
                System.out.println("ref[" + j + "] validity status: " + refValid + ", ref URI: [" + refURI + "]");
            }
        }
    }
...