So signieren Sie nur einen bestimmten Teil von XML

Ich versuche, eine XML-Signatur zu erstellen, indem ich nur Teile der XML-Datei signiere. Nach langem Suchen konnte ich jedoch keine Lösung finden.

Ich benutze Java, um ein XML mit Xpath2-Transformation und EXCLUSIVE-Kanonisierung zu signieren. Wenn ich folgendes XML habe

<?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>

Und unterschreibe es, ich bekomme folgende Ausgabe (Echtdaten durch Dummy ersetzt)

<?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>

Wenn ich die Signatur validiere, ist alles in Ordnung, aber das Problem hier ist, dass ich direkt danach eine XSLT im XML durchführe, die einige Änderungen an einigen Elementen vornimmt, aber nicht an dem signierten Element (ns0:addr), die intakt bleibt. Auch wenn ich ausdrücklich sage, dass nur das "addr" -Element signiert werden soll, wenn ich versuche, Änderungen an einem seiner Elternteile vorzunehmen (payload, msg oderaddr), dann schlägt die Signatur fehl, wenn dies (nach meinem Verständnis) nicht der Fall sein sollte. Wenn ich Änderungen an anderen Elementen vornehme, z. B. an der Kopfzeile, ist die Signatur weiterhin gültig.

Ich habe den XPath-Ausdruck getestet (//*[local-name()='addr']/*) und wählt die richtigen zu signierenden Daten aus (ns2:data), aber es scheint auch alle Elemente zu nehmen, die vom Wurzelelement zu ihm führen (msg, addr).

Ich habe auch versucht, verschiedene Transformationen wie UNION zu verwenden, aber das funktioniert überhaupt nicht.

Weiß jemand, was das Problem sein könnte? Gibt es in Java eine Möglichkeit, genau zu sehen, was signiert wird, wenn das XML zu Debugzwecken signiert wird?

BEARBEITEN:

Beim späteren Ausführen von xslt werden beispielsweise Namespaces vom Element ns0: addr in das Root-Element (msg) verschoben. Außerdem werden der Name und der Namespace des Hauptelements von msg in newmsg (und ein anderer Standardnamespace) geändert signierte Daten (ns2:data) intakt.

Der zum Signieren verwendete Code ist mehr oder weniger der hier erwähnte Codehttp://docs.oracle.com/javase/7/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html

Außer anstelle einer ENVELOPED-Transformation verwende ich eine XPATH2-Transformation:

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);

Und statt ENVELOPED benutze ich auch EXCLUSIVE

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

EDIT2:

Ich habe es geschafft, ein feineres Debuggen des XML-Signaturprozesses zu ermöglichen, und Folgendes erhalten:

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>

Es scheint die korrekten Daten zu signieren, fügt jedoch der Signatur einige zusätzliche Namespaces hinzu, und ich frage mich, ob dies das Problem ist, da diese Namespaces aus den übergeordneten Elementen stammen.

Weiß jemand, wie man es schafft, nicht alle zusätzlichen Namespaces hinzuzufügen?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage