2014-05-08 66 views
0

我正在嘗試爲給定的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,正如我在代碼中所做的那樣,兩行代碼更高?但它不是?

任何人都可以指出我失蹤的是什麼?我會永遠感激。

+0

其他評論:已經給出瞭解決方案,但是Transform本身(我的'OptionalDeflateTransform'類)不必擴展'TransformService',而是'TransformClass'。 – testuser

回答

2

顯然,Apache Santuario loads transforms from a internal map。有一個register 方法,您可能可以使用註冊您的自定義轉換。

+0

我恰好在2分鐘前找到它!顯然實際上有一個'Transform.register(URI,實現類)'方法。有了這個功能,我甚至不需要整個'提供者'和安全註冊系統。謝謝! – testuser

相關問題