I have a WS-Security implementation based on xml-security and am testing interop. When testing against WSS4J (which also uses xml-security) - both using version 1.3.0 - I am having problems because of what appears to be different results of Excl C14N depending on whether the input is a NodeSet or a root node. The problem occurs when using InclusiveNamespaces.
The issue appears to be that when the input is a NodeSet, the InclusiveNamespaces value is ignored. What happens is the following sequence of calls: TransformC14NExclusive.enginePerformTransform(inputWithNodeSet) -> Canonicalizer20010315Excl.engineCanonicalize(inputWithNodeSet, "env ns0 xsi wsu") -> _inclusiveNSSet = "env ns0 xsi wsu" -> CanonicalizerBase.engineCanonicalize(inputWithNodeSet) -> Canonicalizer20010315Excl.engineCanonicalizeXPathNodeSet(xpathNodeSet) -> Canonicalizer20010315Excl.engineCanonicalizeXPathNodeSet(xpathNodeSet, "") -> _inclusiveNSSet = "" So the inclusive namespaces passed in originally are forgotten to be replaced by an empty list. When passing a root node instead of a node set, the inclusive namespace list is used and so the result is different. In the XML below, the document element is env:Envelope and env:Body is that target node for C14N. For the nodeset the result on the SOAP body is (formatting added) <env:Body xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurit y-utility-1.0.xsd" wsu:Id="body"> <ns0:Ping xmlns:ns0="http://xmlsoap.org/Ping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns0:ping"> <ns0:text xsi:type="xsd:string">hello</ns0:text> </ns0:Ping> </env:Body> and for a root node (being the body element in this case) <env:Body xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns0="http://xmlsoap.org/Ping" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurit y-utility-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" wsu:Id="body"> <ns0:Ping xsi:type="ns0:ping"> <ns0:text xsi:type="xsd:string">hello</ns0:text> </ns0:Ping> </env:Body> I attach a test program that compares the 2 ways of doing this on the same document and shows the results (the nodeset result differs from the one above as it does not include any namespace declarations). Is this a bug or am I not understanding the difference between processing based on a nodeset and processing based on a root node? Pete
/** * Copyright Notice * * Copyright (c) 2000-2004, Cape Clear Software. * All Rights Reserved * * This software is protected by copyright and other intellectual * property rights and by international treaties. Any unauthorised * reproduction or distribution of this software or any portion * thereof is strictly prohibited. */ package client.wss4j; import java.io.StringReader; import java.util.Set; import java.util.HashSet; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import org.xml.sax.InputSource; import org.w3c.dom.Document; import org.apache.xml.security.signature.XMLSignatureInput; import org.apache.xml.security.c14n.implementations.Canonicalizer20010315Excl; import org.apache.xml.security.c14n.implementations.Canonicalizer20010315ExclOmitComments; import org.apache.xml.security.utils.XMLUtils; /** * @author Pete Hendry * @version $Id$ */ public class DemoINProblem { private static final String XML = "<env:Envelope" + " xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\"" + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + " xmlns:ns0=\"http://xmlsoap.org/Ping\"" + " xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" + "<env:Body wsu:Id=\"body\">" + "<ns0:Ping xsi:type=\"ns0:ping\">" + "<ns0:text xsi:type=\"xsd:string\">hello</ns0:text>" + "</ns0:Ping>" + "</env:Body>" + "</env:Envelope>"; public static void main( String[] args ) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(false); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new InputSource(new StringReader(XML))); XMLSignatureInput input = new XMLSignatureInput(doc.getDocumentElement().getFirstChild()); // called because this happens during tracing input.setNeedsToBeExpanded(true); Canonicalizer20010315Excl c14n = new Canonicalizer20010315ExclOmitComments(); byte[] bytes = c14n.engineCanonicalize(input, "env ns0 xsi wsu"); System.out.println("ROOT NODE:\n" + new String(bytes) + "\n=======\n"); doc = builder.parse(new InputSource(new StringReader(XML))); Set nodeSet = new HashSet(); XMLUtils.getSet(doc.getDocumentElement().getFirstChild(), nodeSet, null, false); input = new XMLSignatureInput(nodeSet); input.setNeedsToBeExpanded(true); c14n = new Canonicalizer20010315ExclOmitComments(); bytes = c14n.engineCanonicalize(input, "env ns0 xsi wsu"); System.out.println("NODE SET:\n" + new String(bytes) + "\n=======\n"); } }