xades4j.UnsupportedAlgorithmException: неподдерживаемое преобразование в поставщике подписи XML

Я пытаюсь создать подпись XAdES-BES для данного большого двоичного объекта. Для этой подписи мне нужно было бы добавить два преобразования к контенту, прежде чем оно будет подписано: Base64 ( http://www.w3.org/2000/09/xmldsig) и пользовательское (называемое option-deflate),

Проблемы связаны с этим необязательным преобразованием. Я пытаюсь выяснить, как реализовать пользовательское преобразование, зарегистрировать его и, наконец, использовать Xades4J.

До сих пор я много вычислял (спасибо Google и много времени), поэтому я подошел примерно к этому: у меня есть класс Provider, который в конструкторе помещает новый TransformService; В своем основном коде я добавляю своего провайдера в экземпляр Security; затем я пытаюсь добавить преобразование к моему фактическому объекту, который будет подписан.

К сожалению, я всегда получаю одну и ту же ошибку:

Exception in thread "main" xades4j.UnsupportedAlgorithmException: Unsupported transform on XML Signature provider (urn:xml:sig:transform:optional-deflate)
    at xades4j.production.DataObjectDescsProcessor.processTransforms(DataObjectDescsProcessor.java:194)
    at xades4j.production.DataObjectDescsProcessor.process(DataObjectDescsProcessor.java:87)
    at xades4j.production.SignerBES.sign(SignerBES.java:173)
    at xades4j.production.SignerBES.sign(SignerBES.java:122)
    at com.mycompany.Test.createXades(Test.java:199)
    at com.mycompany.Test.main(Test.java:47)
Caused by: org.apache.xml.security.transforms.TransformationException: Unknown transformation. No handler installed for URI urn:xml:sig:transform:optional-deflate
Original Exception was org.apache.xml.security.transforms.InvalidTransformException: Unknown transformation. No handler installed for URI urn:xml:sig:transform:optional-deflate
    at org.apache.xml.security.transforms.Transforms.addTransform(Unknown Source)
    at xades4j.production.DataObjectDescsProcessor.processTransforms(DataObjectDescsProcessor.java:185)
    ... 5 more

Итак, мой код выглядит следующим образом (сокращенно то, что я считаю необходимым здесь):

TransformService учебный класс:

package com.mycompany.security;

import java.io.OutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;

import javax.xml.crypto.Data;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.dsig.TransformService;
import javax.xml.crypto.dsig.TransformException;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;

public class OptionalDeflateTransform extends TransformService {
    public AlgorithmParameterSpec getParameterSpec() {
            return null;
    }
    public Data transform(Data data, XMLCryptoContext context) throws TransformException {
            return null;
    }
    public Data transform(Data data, XMLCryptoContext context, OutputStream os) throws TransformException {
            return null;
    }
    public boolean isFeatureSupported(String feature) {
            return false;
    }
    public void init(TransformParameterSpec params) throws InvalidAlgorithmParameterException {}
    public void marshalParams(XMLStructure parent, XMLCryptoContext context) throws MarshalException {}
    public void init(XMLStructure parent, XMLCryptoContext context) throws InvalidAlgorithmParameterException {}
}

Provider подкласс:

package com.mycompany.security;

import java.security.Provider;

public final class OptionalDeflateProvider extends Provider {
    private static final long serialVersionUID = 8849833178389029123L;

    public OptionalDeflateProvider() {
            super("OptionalDeflate", 1.0, "OptionalDeflate provider 1.0 implementing the OptionalDeflate transform algorithm.");
            put("TransformService.urn:xml:sig:transform:optional-deflate", "com.mycompany.security.OptionalDeflateTransform");
    }

}

И наконец, мой главный Test класс, который содержит фактическую подпись. Без этого преобразования это работает (но хорошо, не добавляет преобразование, которое необходимо). Так что Base64 работает.

protected static void createXades(String content) throws Exception {
    /*Get certificate & private key*/
    Certificates c = new Certificates(); 
    c.initSession(); //some helper class where I can get my certificate & private key for signing

    /*Create a document*/
    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
    Document doc = docBuilder.newDocument();
    Element objectElement = doc.createElement("object");
    doc.appendChild(objectElement);
    Element requestElement = doc.createElement("request");
    requestElement.appendChild(doc.createTextNode(content));
    requestElement.setAttribute("ID", UUID.randomUUID().toString());
    objectElement.appendChild(requestElement);

    /*Key provider, signing profile & signer itself*/
    KeyingDataProvider kp = new CustomKeyingDataProvider(c.getCertificate(), c.getPrivateKey());
    XadesSigningProfile p = new XadesBesSigningProfile(kp);
    p.withAlgorithmsProviderEx(new ProviderEx());
    XadesSigner signer = p.newSigner();

    /*Add the optional deflate provider*/
    Security.addProvider(new OptionalDeflateProvider());
    System.out.println("--- installed providers ---");
    for (Provider pr : Security.getProviders())
            System.out.println(pr.getName());
    System.out.println("---");

    /*Test if we can get the transformservice-instance*/
    TransformService ts = TransformService.getInstance("urn:xml:sig:transform:optional-deflate", "DOM");
    System.out.println(ts.getAlgorithm());
    System.out.println("---");

    /*Signed data*/
    DataObjectDesc flatFile = new DataObjectReference("#" + requestElement.getAttribute("ID"))
            .withTransform(new GenericAlgorithm("http://www.w3.org/2000/09/xmldsig#base64"))
            .withTransform(new GenericAlgorithm("urn:xml:sig:transform:optional-deflate"));
    SignedDataObjects dataObjs = new SignedDataObjects(flatFile);

    /*Actual signing*/
    signer.sign(dataObjs, objectElement);
    log(objectElement.getLastChild());
}

Как видите, я распечатываю некоторые вещи. Я, например, зарегистрировал, что установка работает отлично, и я также зарегистрировал установленных провайдеров. Я получаю это в качестве вывода:

--- installed providers ---
SUN
SunRsaSign
SunEC
SunJSSE
SunJCE
SunJGSS
SunSASL
XMLDSig
SunPCSC
SunMSCAPI
OptionalDeflate
---
urn:xml:sig:transform:optional-deflate
---

Итак, насколько я вижу, провайдер успешно зарегистрирован, TransformService может быть загружен без проблем,... Так что я не вижу, что происходит?

Я также проверил исходный код Xades4j, и что происходит внутри на линии .withTransform(new GenericAlgorithm("urn:xml:sig:transform:optional-deflate")) довольно просто:

import org.apache.xml.security.transforms.Transforms;

...

private Transforms processTransforms(DataObjectDesc dataObjDesc, Document document) throws UnsupportedAlgorithmException {
    Collection<Algorithm> dObjTransfs = dataObjDesc.getTransforms();
    if (dObjTransfs.isEmpty()) {
        return null;
    }
    Transforms transforms = new Transforms(document);
    for (Algorithm dObjTransf : dObjTransfs) {
        try {
            List<Node> transfParams = this.algorithmsParametersMarshaller.marshalParameters(dObjTransf, document);
            if (null == transfParams) {
                transforms.addTransform(dObjTransf.getUri());
            } else {
                transforms.addTransform(dObjTransf.getUri(), DOMHelper.nodeList(transfParams));
            }
        } catch (TransformationException ex) {
            throw new UnsupportedAlgorithmException("Unsupported transform on XML Signature provider", dObjTransf.getUri(), ex);
        }
    }
    return transforms;
}

Точная строка выдает ошибку transforms.addTransform(dObjTransf.getUri()), это transforms объект является "стандартным" объектом apache (org.apache.xml.security.transforms.Transforms объект). Таким образом, я предполагаю, что он сможет получить тот же TransformService, что и в коде, на две строки выше? Но это не так?

Кто-нибудь, кто может указать мне, что я скучаю? Я буду вечно благодарен.

1 ответ

Решение

Судя по всему, Apache Santuario загружает преобразования с внутренней карты. E сть registerметод, который вы, вероятно, можете использовать для регистрации вашего пользовательского преобразования.

Другие вопросы по тегам