Hi,

My XML signature breaks when I convert the signed DOM to String and back again 
to DOM. I'm using jdk1.5.0_06 with 
-Xbootclasspath/p:xalan-2.7.0.jar:xercesImpl-2.7.1.jar:xml-apis-2.0.2.jar:serializer-2.7.0.jar
The following JUnit test demonstrates the issue. Anyone any idea what I'm doing 
wrong here?

Thanks in advance,
Frank


package test.unit.signature;

import java.io.StringReader;
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import junit.framework.TestCase;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xml.security.Init;
import org.apache.xml.security.algorithms.MessageDigestAlgorithm;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.transforms.params.XPathContainer;
import org.apache.xml.security.utils.Constants;
import org.apache.xml.security.utils.XMLUtils;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class SignatureTest extends TestCase {

        private static final Log LOG = LogFactory.getLog(SignatureTest.class);

        public void testSignature() throws Exception {
                // create a document
                DocumentBuilderFactory documentBuilderFactory = 
DocumentBuilderFactory
                                .newInstance();
                documentBuilderFactory.setNamespaceAware(true);
                javax.xml.parsers.DocumentBuilder documentBuilder = 
documentBuilderFactory
                                .newDocumentBuilder();
                org.w3c.dom.Document testDocument = 
documentBuilder.newDocument();

                Element rootElement = 
testDocument.createElementNS("urn:namespace",
                                "tns:document");
                /*
                 * XXX: Doing 'tns:document' here makes the verification to 
fail. With
                 * just 'document' it's OK, but then the namespace gets lost.
                 */
                testDocument.appendChild(rootElement);

                // generate keys
                KeyPair keyPair = 
KeyPairGenerator.getInstance("RSA").generateKeyPair();
                PublicKey publicKey = keyPair.getPublic();
                PrivateKey privateKey = keyPair.getPrivate();

                // init xml-security
                Init.init();

                // create and add signature element
                XMLSignature signature = new XMLSignature(testDocument, null,
                                XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512,
                                Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
                Element signatureElement = signature.getElement();
                rootElement.appendChild(signatureElement);

                // add co-sign reference
                Transforms transforms = new Transforms(testDocument);
                XPathContainer xpath = new XPathContainer(testDocument);
                xpath.setXPathNamespaceContext("ds", Constants.SignatureSpecNS);
                xpath.setXPath("not(ancestor-or-self::ds:Signature)");
                transforms.addTransform(Transforms.TRANSFORM_XPATH, xpath
                                .getElementPlusReturns());
                
transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);
                signature.addDocument("", transforms,
                                MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA512);

                // add public key
                signature.addKeyInfo(publicKey);

                // sign the document
                signature.sign(privateKey);

                // go from DOM to string
                Source source = new DOMSource(testDocument);
                StringWriter stringWriter = new StringWriter();
                Result result = new StreamResult(stringWriter);
                Transformer xformer = 
TransformerFactory.newInstance().newTransformer();
                xformer.transform(source, result);
                String strSignedDocument = stringWriter.getBuffer().toString();
                LOG.debug("signed document: " + strSignedDocument);

                // go from string to DOM
                DocumentBuilderFactory domFactory = DocumentBuilderFactory
                                .newInstance();
                domFactory.setNamespaceAware(true);
                javax.xml.parsers.DocumentBuilder domBuilder = domFactory
                                .newDocumentBuilder();
                StringReader stringReader = new StringReader(strSignedDocument);
                InputSource inputSource = new InputSource(stringReader);
                org.w3c.dom.Document signedDocument = 
domBuilder.parse(inputSource);

                // verify original test document
                NodeList signatureElems = XPathAPI.selectNodeList(testDocument,
                                "//ds:Signature", 
XMLUtils.createDSctx(testDocument, "ds",
                                                Constants.SignatureSpecNS));
                signatureElement = (Element) signatureElems.item(0);
                XMLSignature signatureToVerify = new 
XMLSignature(signatureElement,
                                null);

                boolean signOrigResult = signatureToVerify
                                .checkSignatureValue(publicKey);

                assertTrue(signOrigResult);

                // verify from string loaded document
                signatureElems = XPathAPI.selectNodeList(signedDocument,
                                "//ds:Signature", 
XMLUtils.createDSctx(signedDocument, "ds",
                                                Constants.SignatureSpecNS));
                signatureElement = (Element) signatureElems.item(0);
                signatureToVerify = new XMLSignature(signatureElement, null);

                boolean signResultLoaded = signatureToVerify
                                .checkSignatureValue(publicKey);

                assertTrue(signResultLoaded); // XXX: bang!
        }
}





Reply via email to