Estoy intentando hacer alguna Firma XML firmando solo partes del xml; sin embargo, después de mucha búsqueda no he podido encontrar una solución.Cómo firmar solo una parte específica de XML
Estoy usando Java para firmar un XML usando la transformación Xpath2 y la canonicalización EXCLUSIVA. Si tengo el siguiente código 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 firmarlo, me sale el siguiente resultado (datos reales reemplazados con el maniquí)
<?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 validar la firma, todo está bien, sin embargo el problema aquí es justo después de esto realizo un XSLT en el XML que realiza algunos cambios a algunos elementos pero no al elemento firmado (ns0:addr
) que se deja intacto. Aunque explícitamente digo que solo se debe firmar el elemento "addr", si intento realizar cambios en cualquiera de sus padres (payload
, msg
o addr
), entonces falla la firma cuando (según mi entender) no debería . Si realizo cambios en otros elementos, como cualquier elemento dentro del encabezado, la firma sigue siendo válida.
He probado la expresión XPath (//*[local-name()='addr']/*
) y selecciona los datos correctos a ser firmados (ns2:data
) pero parece estar tomando también todos los elementos que conducen a él a partir del elemento raíz (msg
, addr
).
También he intentado utilizar diferentes transformaciones como UNION pero eso no funciona en absoluto.
¿Alguien sabe cuál es el problema? ¿Hay alguna forma, en Java, de ver exactamente qué se está firmando cuando se firma el XML con fines de depuración?
EDIT:
La carrera XSLT tarde va a hacer las cosas como mover espacios de nombres de la ns0: addr elemento al elemento raíz (MSG) y también se cambia el nombre principal elemento y el espacio de nombres de MSG a newmsg (y un espacio de nombres predeterminado diferente) pero dejando intactos los datos firmados (ns2:data
).
El código utilizado para firmar es más o menos el código mencionado aquí http://docs.oracle.com/javase/7/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html
Excepto que en vez de un ENVUELTO transformo Estoy utilizando un XPATH2 transformar:
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 ENVUELTO soy el uso EXCLUSIVO
canonicalisationMethod = fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null);
Edit2:
Me han logrado habilitar la depuración fina del proceso xml firma y conseguido 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 ser que firma la información correcta, sin embargo, también está agregando algunos espacios de nombres adicionales a la firma que me pregunto si ese es el problema, ya que esos namspaces se toman de los elementos principales.
¿Alguien sabe cómo hacerlo para que no se agreguen todos los espacios de nombres adicionales?
Sí, está firmando el XML completo (solo mirando ''). ¿Puede mostrarnos el código que usa para firmar el documento XML? –
dusan
Trataré de poner algo del código más tarde una vez que esté frente a él nuevamente. Sí, el 'uri =" "', sin embargo, esto se debe al uso de xpath en su lugar para seleccionar qué nodo está firmado. ¿No debería ser ese el caso? Además, si cambio otros nodos internos, como el encabezado, la firma sigue siendo válida, lo que me lleva a pensar que algo no está funcionando como debería. – ByteFlinger
Me parece bien. ¿Puedes incluir tu XML después de la transformación xslt? Además, cuando dice que modificó 'msg' o' payload', ¿agregó un nodo secundario o hizo un cambio de nombre? – pd40