2012-09-20 15 views
7

Sto provando a fare un po 'di firma XML firmando solo parti dell'xml ma dopo molte ricerche non sono stato in grado di trovare una soluzione.Come firmare solo una parte specifica di XML

Sto usando java per firmare un XML utilizzando la trasformata Xpath2 e la canonicalizzazione ESCLUSIVA. Se ho il seguente codice XML

<?xml version="1.0" encoding="UTF-8"?> 
<msg xmlns="http://someaddress/ad/m1" xmlns:ns1="http://someotheraddres/ad/m2" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"> 
<header> 
    <id>wsfrwerwerwer</id> 
    <name>addr</name> 
    <somenode> 
     <trace>ND</trace> 
    </somenode> 
</header> 
<payload><ns0:addr xmlns:ns0="http://someaddres/ad/m3"><ns2:data xmlns:ns2="http://someaddres/ad/m3"> 
      <ns2:name>somevalue</ns2:name> 
      <ns2:value>354</ns2:value> 
     </ns2:data> 
    </ns0:addr> 
</payload> 
</msg> 

e firmare, ottengo il seguente output (dati reali sostituiti con il manichino)

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<msg xmlns="http://someaddress/ad/m1" xmlns:ns1="http://someotheraddres/ad/m2" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"> 
<header> 
    <id>wsfrwerwerwer</id> 
    <name>addr</name> 
    <somenode> 
     <trace>ND</trace> 
    </somenode> 
</header> 
<payload> 
    <ns0:addr xmlns:ns0="http://someaddres/ad/m3"> 
     <ns2:data xmlns:ns2="http://someaddres/ad/m3"> 
      <ns2:name>somevalue</ns2:name> 
      <ns2:value>354</ns2:value> 
     </ns2:data> 
    </ns0:addr> 
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> 
     <SignedInfo> 
      <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
      <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> 
      <Reference URI=""> 
       <Transforms> 
        <Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2"> 
         <XPath xmlns="http://www.w3.org/2002/06/xmldsig-filter2" xmlns:ns0="http://someaddres/ad/m3" Filter="intersect">//*[local-name()='addr']/*</XPath> 
        </Transform> 
       </Transforms> 
       <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> 
       <DigestValue>sdlfjdeklsdfngf</DigestValue> 
      </Reference> 
     </SignedInfo> 
     <SignatureValue>femhjgklnlkl</SignatureValue> 
     <KeyInfo> 
      <X509Data> 
       <X509Certificate>swerwerwrwerwerwe</X509Certificate> 
      </X509Data> 
     </KeyInfo> 
    </Signature> 
</payload> 
</msg> 

Se convalidare la firma, è tutto a posto ma il problema qui è subito dopo eseguo un XSLT nell'XML che esegue alcune modifiche ad alcuni elementi ma non l'elemento firmato (ns0:addr) che viene lasciato intatto. Anche se dichiaro esplicitamente che solo l'elemento "addr" dovrebbe essere firmato, se provo a eseguire modifiche a uno dei suoi genitori (payload, msg o addr), fallisce la firma quando (secondo la mia comprensione) non dovrebbe . Se eseguo modifiche ad altri elementi come qualsiasi cosa all'interno dell'intestazione, la firma è ancora valida.

Ho testato l'espressione XPath (//*[local-name()='addr']/*) e seleziona i dati corretti da firmare (ns2:data) ma sembra essere lento anche tutti gli elementi che conducono ad esso a partire dall'elemento radice (msg, addr).

Ho anche provato a utilizzare diverse trasformazioni come UNION ma questo non funziona affatto.

Qualcuno sa quale potrebbe essere il problema? C'è un modo, in Java, per vedere esattamente ciò che viene firmato quando si firma il codice XML per scopi di debug?

EDIT:

La corsa XSLT poi farà le cose come spostare gli spazi dei nomi dal ns0: addr elemento con l'elemento radice (msg) ed inoltre sarà cambiare il nome dell'elemento principale e dello spazio dei nomi da msg al newmsg (e un diverso spazio dei nomi predefinito) ma lasciando intatti i dati firmati (ns2:data).

Il codice utilizzato per firmare è più o meno il codice di cui qui http://docs.oracle.com/javase/7/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html

tranne che invece di un AVVOLTO trasformo Sto utilizzando un XPATH2 trasformare:

Map<String, String> namespaceMap = new HashMap<String, String>(0); 
namespaceMap.put("ns0", "http://someaddres/ad/m3"); 
XPathType xPathType = new XPathType(xPathParameters, Filter.INTERSECT, namespaceMap); 
List<XPathType> xPathList = new ArrayList<XPathType>(0); 
xPathList.add(xPathType) 
XPathFilter2ParameterSpec xPathFilter2ParameterSpec = new XPathFilter2ParameterSpec(xPathList); 
transform = fac.newTransform(CanonicalizationMethod.XPATH2, xPathFilter2ParameterSpec); 

E anche al posto di AVVOLTO Sono utilizzando ESCLUSIVO

canonicalisationMethod = fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null); 

EDIT2:

Sono riuscito a attivare il debug più fine del processo xml firma e ha ottenuto la seguente:

FINER: Pre-digested input: 21-Sep-2012 10:51:39 org.jcp.xml.dsig.internal.DigesterOutputStream write FINER: <ns2:data xmlns="http://someaddress/ad/m1" xmlns:ns0="http://someaddres/ad/m3" xmlns:ns1="http://someotheraddres/ad/m2" xmlns:ns2="http://someaddres/ad/m3"> <ns2:name>somevalue</ns2:name> <ns2:value>354</ns2:value> </ns2:data>

Sembra essere la firma e la correttezza dei dati tuttavia è anche l'aggiunta di alcuni spazi dei nomi in più per la firma, che mi fa chiedere se questo è il problema dal momento che quei namspace sono presi dagli elementi genitore.

Qualcuno sa come fare a non aggiungere tutti gli spazi dei nomi aggiuntivi?

+0

Sì, stai firmando l'XML completo (solo guardando ''). Puoi mostrarci il codice che usi per firmare il documento XML? – dusan

+0

Proverò a inserire un po 'di codice più tardi una volta che mi troverò di nuovo davanti a esso. Sì, 'uri =" "' tuttavia questo è dovuto all'utilizzo di xpath per selezionare quale nodo è stato firmato. Non dovrebbe essere così? Inoltre, se cambio altri nodi interni come l'intestazione, la firma è ancora valida e ciò mi porta a credere che qualcosa stia funzionando, ma non come dovrebbe essere. – ByteFlinger

+0

Mi sembra a posto. Puoi elencare il tuo XML dopo la trasformazione xslt? Inoltre, quando dici di aver modificato 'msg' o' payload', hai aggiunto un nodo figlio o fatto un rinominare? – pd40

risposta

1

Dopo molti combattimenti con le firme XML sono finalmente arrivato a una soluzione accettabile (anche se non ideale).

A quanto pare una canonica esclusiva non è sufficiente. È necessario aggiungere anche una trasformazione esclusiva dopo tutti gli altri trasformatori. A seguito dei frammenti di codice che ho scritto sopra:

List<Transform> transforms = new ArrayList<Transform>() 
transforms.add(transform) 
fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null) 

Questo farà in modo che tutti gli altri spazi dei nomi al di fuori degli elementi firmati non saranno presi in considerazione (anche se ha l'effetto aggiunto che l'inserimento di namespace (s) all'interno della l'elemento firmato è permesso).

Sembra inoltre che qualsiasi elemento nel percorso x dell'elemento firmato verrà preso in considerazione, quindi se si ha il seguente xpath /root/A/B firmerà il tag B, tuttavia non sarà possibile modificare il nome del tag di A o elementi radice.

Questo può essere risolto utilizzando un percorso x con meno elementi come //B.

Credo che sia possibile superare questo problema anche se finora non sono stato in grado di farlo.

0

Ci sono dei parametri, relativi allo spazio dei nomi, che possono essere passati a Exclusive XML Canonicalization che descrivono lo InclusiveNamespaces PrefixList.

Si potrebbe provare a passare un ExcC14NParameterSpec a newCanonicalizationMethod() utilizzando un elenco di prefisso per vedere se che colpisce la canonica dei namespace.

+1

Grazie. Ho provato a utilizzare questo: 'Elenco prefixList = new ArrayList (); prefissoList.add ("ns2"); C14NMethodParameterSpec c14NMethodParameterSpec = new ExcC14NParameterSpec (prefixList); canonicalisationMethod = xmlSigFactory.newCanonicalizationMethod (CanonicalizationMethod.EXCLUSIVE, c14NMethodParameterSpec); ' ma non è stato apportato alcun cambiamento. L'immagine sembra cambiare a seconda se aggiungo più o meno prefissi alla lista, ma ancora non mi permette di cambiare gli elementi sopra quello che dovrebbe essere firmato. – ByteFlinger