我正在嘗試爲給定的blob創建XAdES-BES簽名。對於這個簽名,我需要在內容簽名前添加兩個變換:Base64(http://www.w3.org/2000/09/xmldsig#base64)&一個自定義的(稱爲可選deflate)。xades4j.UnsupportedAlgorithmException:XML簽名提供程序上的不受支持的轉換
問題在於可選的轉換。我試圖找出如何實現自定義Transform,註冊它,並最終讓Xades4J使用它。我得到了很多(感謝谷歌和很多時間),所以我粗略地這樣說:我有一個Provider類,在構造函數中,將新的TransformService;在我的主代碼中,我將我的提供程序添加到安全實例;然後,我嘗試將轉換添加到我的實際待簽名對象中。
不幸的是,我總是得到同樣的錯誤:
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,正如我在代碼中所做的那樣,兩行代碼更高?但它不是?
任何人都可以指出我失蹤的是什麼?我會永遠感激。
其他評論:已經給出瞭解決方案,但是Transform本身(我的'OptionalDeflateTransform'類)不必擴展'TransformService',而是'TransformClass'。 – testuser