Cómo firmar solo una parte específica de XML

Estoy intentando hacer algo de firma XML firmando solo partes del xml, sin embargo, después de mucho buscar no he podido encontrar una solución.

Estoy usando java para firmar un XML usando la transformación Xpath2 y la canonicalización EXCLUSIVA. Si tengo el siguiente 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>

Y fírmelo, obtengo la siguiente salida (datos reales reemplazados con un dummy)

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

Si valido la firma, todo está bien, sin embargo, el problema aquí es que, justo después de esto, realizo un XSLT en el XML que realiza algunos cambios en algunos elementos pero no en el elemento firmado (ns0:addr) que queda intacto. Aunque digo explícitamente que solo se debe firmar el elemento "addr", si intento realizar cambios en alguno de sus padres (payload, msg oaddr), luego falla la firma cuando (según mi entendimiento) no debería. Si realizo cambios en otros elementos, como cualquier cosa dentro del encabezado, la firma sigue siendo válida.

He probado la expresión XPath (//*[local-name()='addr']/*) y selecciona los datos correctos a firmar (ns2:data) pero parece estar tomando también todos los elementos que llevan a ella a partir del elemento raíz (msg, addr).

También he intentado usar diferentes transformaciones como UNION pero eso no funciona en absoluto.

¿Alguien sabe cuál podría ser el problema? ¿Hay alguna forma, en Java, de ver exactamente qué se está firmando cuando se firma el XML con fines de depuración?

EDITAR:

La ejecución de xslt más adelante hará cosas como mover espacios de nombres del elemento ns0: addr al elemento raíz (msg) y también cambiará el nombre del elemento principal y el espacio de nombres de msg a newmsg (y un espacio de nombres predeterminado diferente) pero dejando el datos firmados (ns2:data) intacto.

El código utilizado para firmarlo es más o menos el código mencionado aquí.http://docs.oracle.com/javase/7/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html

Excepto en lugar de una transformación ENVELOPED, estoy usando una transformación XPATH2:

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

Y también en lugar de SOBRADO estoy usando EXCLUSIVO

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

EDIT2:

Logré habilitar una depuración más precisa del proceso de firma xml y obtuve lo siguiente:

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>

Parece estar firmando los datos correctos, sin embargo, también está agregando algunos espacios de nombres adicionales a la firma, lo que me hace preguntarme si ese es el problema, ya que esos espacios de nombres se toman de los elementos principales.

¿Alguien sabe cómo hacer que no se agreguen todos los espacios de nombres adicionales?

Respuestas a la pregunta(2)

Su respuesta a la pregunta