/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
 */
package javax.xml.crypto.test.dsig;


import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyStore;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import java.util.*;

import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;

import javax.xml.crypto.KeySelector;
import javax.xml.crypto.URIDereferencer;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dom.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.*;
import javax.xml.crypto.dsig.spec.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.xml.security.utils.Constants;
import org.apache.xml.security.utils.XMLUtils;

import javax.xml.crypto.test.KeySelectors;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;


/**
 * Test that recreates merlin-xmldsig-twenty-three test vectors but with
 * different keys and X.509 data.
 *
 */
public class CreateBaltimore23Test {

    private XMLSignatureFactory fac;
    private KeyInfoFactory kifac;
    private CanonicalizationMethod withoutComments;
    private Transform withComments;
    private SignatureMethod dsaSha1, rsaSha1;
    private DigestMethod sha1;
    private KeyInfo dsa, rsa;
    private KeySelector kvks = new KeySelectors.KeyValueKeySelector();
    private KeySelector sks;
    private Key signingKey;
    private PublicKey validatingKey;
    private Certificate signingCert;
    private KeyStore ks;
    private final URIDereferencer ud;

    static {
        Security.insertProviderAt
            (new org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI(), 1);
    }

    public CreateBaltimore23Test() throws Exception {
        fac = XMLSignatureFactory.getInstance
            ("DOM", new org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI());
        kifac = fac.getKeyInfoFactory();

        // get key & self-signed certificate from keystore
        String fs = System.getProperty("file.separator");
        String base = System.getProperty("basedir") == null ? "./": System.getProperty("basedir");

        try (FileInputStream fis = new FileInputStream
            (base + fs + "src/test/resources" + fs + "test.jks")) {
            ks = KeyStore.getInstance("JKS");
            ks.load(fis, "changeit".toCharArray());
        }
        signingKey = ks.getKey("mullan", "changeit".toCharArray());
        signingCert = ks.getCertificate("mullan");
        validatingKey = signingCert.getPublicKey();

        // create common objects
        withoutComments = fac.newCanonicalizationMethod
            (CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null);
        withComments = fac.newTransform
            (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
             (TransformParameterSpec) null);
        dsaSha1 = fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null);
        sha1 = fac.newDigestMethod(DigestMethod.SHA1, null);
        dsa = kifac.newKeyInfo(Collections.singletonList
            (kifac.newKeyValue(validatingKey)));
        rsa = kifac.newKeyInfo(Collections.singletonList
            (kifac.newKeyValue(TestUtils.getPublicKey("RSA"))));
        rsaSha1 = fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
        sks = new KeySelectors.SecretKeySelector("secret".getBytes(StandardCharsets.US_ASCII));

        ud = new LocalHttpCacheURIDereferencer();
    }

    @org.junit.Test
    public void test_create_signature_enveloped_dsa() throws Exception {
        // create SignedInfo
        SignedInfo si = fac.newSignedInfo
            (withoutComments, dsaSha1, Collections.singletonList
                (fac.newReference
                    ("", sha1, Collections.singletonList
                        (fac.newTransform(Transform.ENVELOPED,
                         (TransformParameterSpec) null)),
                 null, null)));

        // create XMLSignature
        XMLSignature sig = fac.newXMLSignature(si, dsa);

        Document doc = XMLUtils.newDocument();
        Element envelope = doc.createElementNS
            ("http://example.org/envelope", "Envelope");
        envelope.setAttributeNS
            (Constants.NamespaceSpecNS, "xmlns", "http://example.org/envelope");
        doc.appendChild(envelope);

        DOMSignContext dsc = new DOMSignContext(signingKey, envelope);

        sig.sign(dsc);

        DOMValidateContext dvc = new DOMValidateContext
            (kvks, envelope.getFirstChild());
        XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);

        assertEquals(sig, sig2);

        assertTrue(sig2.validate(dvc));
    }

    @org.junit.Test
    public void test_create_signature_enveloping_b64_dsa() throws Exception {
        test_create_signature_enveloping(dsaSha1, dsa, signingKey, kvks, true);
    }

    @org.junit.Test
    public void test_create_signature_enveloping_dsa() throws Exception {
        test_create_signature_enveloping(dsaSha1, dsa, signingKey, kvks, false);
    }

    @org.junit.Test
    public void test_create_signature_enveloping_hmac_sha1_40()
        throws Exception {
        SignatureMethod hmacSha1 = fac.newSignatureMethod
            (SignatureMethod.HMAC_SHA1, new HMACParameterSpec(40));
        try {
            test_create_signature_enveloping(hmacSha1, null,
                TestUtils.getSecretKey("secret".getBytes(StandardCharsets.US_ASCII)), sks, false);
            fail("Expected HMACOutputLength Exception");
        } catch (XMLSignatureException xse) {
            System.out.println(xse.getMessage());
            // pass
        }
    }

    @org.junit.Test
    public void test_create_signature_enveloping_hmac_sha1()
        throws Exception {
        SignatureMethod hmacSha1 = fac.newSignatureMethod
            (SignatureMethod.HMAC_SHA1, null);
        test_create_signature_enveloping(hmacSha1, null,
            TestUtils.getSecretKey("secret".getBytes(StandardCharsets.US_ASCII)), sks, false);
    }

    @org.junit.Test
    public void test_create_signature_enveloping_rsa() throws Exception {
        test_create_signature_enveloping(rsaSha1, rsa,
            TestUtils.getPrivateKey("RSA"), kvks, false);
    }

    @org.junit.Test
    public void test_create_signature_external_b64_dsa() throws Exception {
        test_create_signature_external(dsaSha1, dsa, signingKey, kvks, true);
    }

    @org.junit.Test
    public void test_create_signature_external_dsa() throws Exception {
        test_create_signature_external(dsaSha1, dsa, signingKey, kvks, false);
    }

    @org.junit.Test
    public void test_create_signature_keyname() throws Exception {
        KeyInfo kn = kifac.newKeyInfo(Collections.singletonList
            (kifac.newKeyName("mullan")));
        test_create_signature_external(dsaSha1, kn, signingKey,
            new X509KeySelector(ks), false);
    }

    @org.junit.Test
    public void test_create_signature_retrievalmethod_rawx509crt()
        throws Exception {
        KeyInfo rm = kifac.newKeyInfo(Collections.singletonList
            (kifac.newRetrievalMethod
            ("certs/mullan.crt", X509Data.RAW_X509_CERTIFICATE_TYPE, null)));
        test_create_signature_external(dsaSha1, rm, signingKey,
            new X509KeySelector(ks), false);
    }

    @org.junit.Test
    public void test_create_signature_x509_crt_crl() throws Exception {

        //
        // This test fails with the IBM JDK
        //
        if ("IBM Corporation".equals(System.getProperty("java.vendor"))) {
            return;
        }

        List<Object> xds = new ArrayList<>();
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        xds.add(signingCert);
        String fs = System.getProperty("file.separator");
        String base = System.getProperty("basedir") == null ? "./": System.getProperty("basedir");
        FileInputStream fis = new FileInputStream(
            base + fs + "src/test/resources" + fs + "ie" + fs +
             "baltimore" + fs + "merlin-examples" + fs +
             "merlin-xmldsig-twenty-three" + fs + "certs" + fs + "crl");
        X509CRL crl = (X509CRL) cf.generateCRL(fis);
        fis.close();
        xds.add(crl);
        KeyInfo crt_crl = kifac.newKeyInfo(Collections.singletonList
            (kifac.newX509Data(xds)));

        test_create_signature_external(dsaSha1, crt_crl, signingKey,
            new X509KeySelector(ks), false);
    }

    @org.junit.Test
    public void test_create_signature_x509_crt() throws Exception {
        //
        // This test fails with the IBM JDK
        //
        if ("IBM Corporation".equals(System.getProperty("java.vendor"))) {
            return;
        }

        KeyInfo crt = kifac.newKeyInfo(Collections.singletonList
            (kifac.newX509Data(Collections.singletonList(signingCert))));

        test_create_signature_external(dsaSha1, crt, signingKey,
            new X509KeySelector(ks), false);
    }

    @org.junit.Test
    public void test_create_signature_x509_is() throws Exception {
        //
        // This test fails with the IBM JDK
        //
        if ("IBM Corporation".equals(System.getProperty("java.vendor"))) {
            return;
        }

        KeyInfo is = kifac.newKeyInfo(Collections.singletonList
            (kifac.newX509Data(Collections.singletonList
            (kifac.newX509IssuerSerial
            ("CN=Sean Mullan,DC=sun,DC=com",
            new BigInteger("47cdb772", 16))))));
        test_create_signature_external(dsaSha1, is, signingKey,
            new X509KeySelector(ks), false);
    }

    @org.junit.Test
    public void test_create_signature_x509_ski() throws Exception {
        KeyInfo ski = kifac.newKeyInfo(Collections.singletonList
            (kifac.newX509Data(Collections.singletonList
            ("keyid".getBytes(StandardCharsets.US_ASCII)))));

        test_create_signature_external(dsaSha1, ski, signingKey,
            KeySelector.singletonKeySelector(validatingKey), false);
    }

    @org.junit.Test
    public void test_create_signature_x509_sn() throws Exception {
        //
        // This test fails with the IBM JDK
        //
        if ("IBM Corporation".equals(System.getProperty("java.vendor"))) {
            return;
        }

        KeyInfo sn = kifac.newKeyInfo(Collections.singletonList
            (kifac.newX509Data(Collections.singletonList
            ("CN=Sean Mullan,DC=sun,DC=com"))));

        test_create_signature_external(dsaSha1, sn, signingKey,
            new X509KeySelector(ks), false);
    }

    @org.junit.Test
    public void test_create_signature() throws Exception {

        //
        // This test fails with the IBM JDK
        //
        if ("IBM Corporation".equals(System.getProperty("java.vendor"))) {
            return;
        }

        // set up reusable objects
        Transform env = fac.newTransform(Transform.ENVELOPED,
            (TransformParameterSpec) null);

        // create references
        List<Reference> refs = new ArrayList<>();

        // Reference 1
        refs.add(fac.newReference("http://www.w3.org/TR/xml-stylesheet", sha1));

        // Reference 2
        refs.add(fac.newReference
            ("http://www.w3.org/Signature/2002/04/xml-stylesheet.b64",
            sha1, Collections.singletonList
            (fac.newTransform(Transform.BASE64,
             (TransformParameterSpec) null)), null, null));

        // Reference 3
        refs.add(fac.newReference("#object-1", sha1, Collections.singletonList
            (fac.newTransform(Transform.XPATH,
            new XPathFilterParameterSpec("self::text()"))),
            XMLObject.TYPE, null));

        // Reference 4
        String expr = "\n"
          + " ancestor-or-self::dsig:SignedInfo			 " + "\n"
          + "  and                                               " + "\n"
          + " count(ancestor-or-self::dsig:Reference |		 " + "\n"
          + "	   here()/ancestor::dsig:Reference[1]) >	 " + "\n"
          + " count(ancestor-or-self::dsig:Reference)		 " + "\n"
          + "  or                                                " + "\n"
          + " count(ancestor-or-self::node() |			 " + "\n"
          + "	   id('notaries')) =				 " + "\n"
          + " count(ancestor-or-self::node())			 " + "\n";

        new XPathFilterParameterSpec(expr,
            Collections.singletonMap("dsig", XMLSignature.XMLNS));
//        refs.add(fac.newReference("", sha1, Collections.singletonList
//	    (fac.newTransform(Transform.XPATH, xfp)),
//	    XMLObject.TYPE, null));

        // Reference 5
        refs.add(fac.newReference("#object-2", sha1, Collections.singletonList
            (fac.newTransform(Transform.BASE64, (TransformParameterSpec) null)),
            XMLObject.TYPE, null));

        // Reference 6
        refs.add(fac.newReference
            ("#manifest-1", sha1, null, Manifest.TYPE, null));

        // Reference 7
        refs.add(fac.newReference("#signature-properties-1", sha1, null,
            SignatureProperties.TYPE, null));

        // Reference 8
        List<Transform> transforms = new ArrayList<>();
        transforms.add(env);
        refs.add(fac.newReference("", sha1, transforms, null, null));

        // Reference 9
        transforms.add(withComments);
        refs.add(fac.newReference("", sha1, transforms, null, null));

        // Reference 10
        refs.add(fac.newReference("#xpointer(/)",
            sha1, Collections.singletonList(env), null, null));

        // Reference 11
        refs.add(fac.newReference("#xpointer(/)", sha1, transforms,
            null, null));

        // Reference 12
        refs.add
            (fac.newReference("#object-3", sha1, null, XMLObject.TYPE, null));

        // Reference 13
        refs.add(fac.newReference("#object-3", sha1,
            Collections.singletonList(withComments), XMLObject.TYPE, null));

        // Reference 14
        refs.add(fac.newReference("#xpointer(id('object-3'))", sha1, null,
            XMLObject.TYPE, null));

        // Reference 15
        refs.add(fac.newReference("#xpointer(id('object-3'))", sha1,
            Collections.singletonList(withComments), XMLObject.TYPE, null));

        // Reference 16
        refs.add(fac.newReference("#reference-2", sha1));

        // Reference 17
        refs.add(fac.newReference("#manifest-reference-1", sha1, null,
            null, "reference-1"));

        // Reference 18
        refs.add(fac.newReference("#reference-1", sha1, null, null,
            "reference-2"));

        // create SignedInfo
        SignedInfo si = fac.newSignedInfo(withoutComments, dsaSha1, refs);

        // create keyinfo
        XPathFilterParameterSpec xpf = new XPathFilterParameterSpec(
            "ancestor-or-self::dsig:X509Data",
            Collections.singletonMap("dsig", XMLSignature.XMLNS));
        RetrievalMethod rm = kifac.newRetrievalMethod("#object-4",
            X509Data.TYPE, Collections.singletonList(fac.newTransform
            (Transform.XPATH, xpf)));
        KeyInfo ki = kifac.newKeyInfo(Collections.singletonList(rm), null);

        Document doc = XMLUtils.newDocument();

        // create objects
        List<XMLObject> objs = new ArrayList<>();

        // Object 1
        objs.add(fac.newXMLObject(Collections.singletonList
            (new DOMStructure(doc.createTextNode("I am the text."))),
            "object-1", "text/plain", null));

        // Object 2
        objs.add(fac.newXMLObject(Collections.singletonList
            (new DOMStructure(doc.createTextNode("SSBhbSB0aGUgdGV4dC4="))),
            "object-2", "text/plain", Transform.BASE64));

        // Object 3
        Element nc = doc.createElementNS(null, "NonCommentandus");
        nc.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "");
        nc.appendChild(doc.createComment(" Commentandum "));
        objs.add(fac.newXMLObject(Collections.singletonList
            (new DOMStructure(nc)), "object-3", null, null));

        // Manifest
        List<Reference> manRefs = new ArrayList<>();

        // Manifest Reference 1
        manRefs.add(fac.newReference("http://www.w3.org/TR/xml-stylesheet",
            sha1, null, null, "manifest-reference-1"));

        // Manifest Reference 2
        manRefs.add(fac.newReference("#reference-1", sha1));

        // Manifest Reference 3
        List<Transform> manTrans = new ArrayList<>();
        String xslt = ""
          + "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'\n"
          + "		 xmlns='http://www.w3.org/TR/xhtml1/strict' \n"
          + "		 exclude-result-prefixes='foo' \n"
          + "		 version='1.0'>\n"
          + "  <xsl:output encoding='UTF-8' \n"
          + "		indent='no' \n"
          + "		method='xml' />\n"
          + "  <xsl:template match='/'>\n"
          + "    <html>\n"
          + "	<head>\n"
          + "	 <title>Notaries</title>\n"
          + "	</head>\n"
          + "	<body>\n"
          + "	 <table>\n"
          + "	   <xsl:for-each select='Notaries/Notary'>\n"
          + "		<tr>\n"
          + "		<th>\n"
          + "		 <xsl:value-of select='@name' />\n"
          + "		</th>\n"
          + "		</tr>\n"
          + "	   </xsl:for-each>\n"
          + "	 </table>\n"
          + "	</body>\n"
          + "    </html>\n"
          + "  </xsl:template>\n"
          + "</xsl:stylesheet>\n";
        Document docxslt = null;
        try (InputStream is = new ByteArrayInputStream(xslt.getBytes())) {
            docxslt = XMLUtils.read(is, false);
        }
        Node xslElem = docxslt.getDocumentElement();

        manTrans.add(fac.newTransform(Transform.XSLT,
            new XSLTTransformParameterSpec(new DOMStructure(xslElem))));
        manTrans.add(fac.newTransform(CanonicalizationMethod.INCLUSIVE,
            (TransformParameterSpec) null));
        // Comment out Manifest Reference 3, for some reason xalan is throwing NPE
        // when Transform is processed.
        //	manRefs.add(fac.newReference("#notaries", sha1, manTrans, null, null));

        objs.add(fac.newXMLObject(Collections.singletonList
            (fac.newManifest(manRefs, "manifest-1")), null, null, null));

        // SignatureProperties
        Element sa = doc.createElementNS("urn:demo", "SignerAddress");
        sa.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "urn:demo");
        Element ip = doc.createElementNS("urn:demo", "IP");
        ip.appendChild(doc.createTextNode("192.168.21.138"));
        sa.appendChild(ip);
        SignatureProperty sp = fac.newSignatureProperty
            (Collections.singletonList(new DOMStructure(sa)),
            "#signature", null);
        SignatureProperties sps = fac.newSignatureProperties
            (Collections.singletonList(sp), "signature-properties-1");
        objs.add(fac.newXMLObject(Collections.singletonList(sps), null,
            null, null));

        // Object 4
        List<Object> xds = new ArrayList<>();
        xds.add("CN=Sean Mullan,DC=sun,DC=com");
        xds.add(kifac.newX509IssuerSerial
            ("CN=Sean Mullan,DC=sun,DC=com",
            new BigInteger("47cdb772", 16)));
        xds.add(signingCert);
        objs.add(fac.newXMLObject(Collections.singletonList
            (kifac.newX509Data(xds)), "object-4", null, null));

        // create XMLSignature
        XMLSignature sig = fac.newXMLSignature(si, ki, objs, "signature", null);

        // create envelope header
        Element envelope = doc.createElementNS
            ("http://example.org/usps", "Envelope");
        envelope.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns",
            "http://example.org/usps");
        envelope.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:foo",
            "http://example.org/foo");
        doc.appendChild(envelope);
        Element dearSir = doc.createElementNS
            ("http://example.org/usps", "DearSir");
        dearSir.appendChild(doc.createTextNode("foo"));
        envelope.appendChild(dearSir);
        Element body = doc.createElementNS("http://example.org/usps", "Body");
        body.appendChild(doc.createTextNode("bar"));
        envelope.appendChild(body);
        Element ys = doc.createElementNS
            ("http://example.org/usps", "YoursSincerely");
        envelope.appendChild(ys);

        // create envelope footer
        Element ps = doc.createElementNS
            ("http://example.org/usps", "PostScript");
        ps.appendChild(doc.createTextNode("bar"));
        envelope.appendChild(ps);
        Element notaries = doc.createElementNS(null, "Notaries");
        notaries.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "");
        notaries.setAttributeNS(null, "Id", "notaries");
        Element notary1 = doc.createElementNS(null, "Notary");
        notary1.setAttributeNS(null, "name", "Great, A. T.");
        Element notary2 = doc.createElementNS(null, "Notary");
        notary2.setAttributeNS(null, "name", "Hun, A. T.");
        notaries.appendChild(notary1);
        notaries.appendChild(notary2);
        envelope.appendChild(notaries);
        envelope.appendChild(doc.createComment(" Commentary "));

        DOMSignContext dsc = new DOMSignContext(signingKey, ys);
        dsc.setIdAttributeNS(notaries, null, "Id");
        dsc.setURIDereferencer(ud);

        sig.sign(dsc);

        // DOM L2 does not support the creation of DOCTYPEs, so instead
        // we insert it before the document using a StringWriter
        //	String docType =
        //	    "<!DOCTYPE Envelope [\n"
        //  	  + "<!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>\n"
        //          + "<!ENTITY c14n 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'>\n"
        //          + "<!ENTITY xpath 'http://www.w3.org/TR/1999/REC-xpath-19991116'>\n"
        //          + "<!ENTITY xslt 'http://www.w3.org/TR/1999/REC-xslt-19991116'>\n"
        //          + "<!ATTLIST Notaries Id ID #IMPLIED>\n"
        //          + "]>\n";
                StringWriter sw = new StringWriter();
        //	sw.write(docType);

        dumpDocument(doc, sw);

        // read document back into DOM tree
        try {
            doc = XMLUtils.read(new InputSource(new StringReader(sw.toString())), false);
        } catch (SAXParseException spe) {
            System.err.println("line:" + spe.getLineNumber());
            System.err.println("xml:" + sw.toString());
        }
        Element sigElement = SignatureValidator.getSignatureElement(doc);
        if (sigElement == null) {
            throw new Exception("Couldn't find signature Element");
        }

        DOMValidateContext dvc = new DOMValidateContext
            (new X509KeySelector(ks), sigElement);
        File f = new File(
            System.getProperty("dir.test.vector.baltimore") +
            System.getProperty("file.separator") +
            "merlin-xmldsig-twenty-three" +
            System.getProperty("file.separator"));
        dvc.setBaseURI(f.toURI().toString());
        dvc.setURIDereferencer(ud);

        // register Notaries ID
        //	Element notariesElem =
        //	    (Element) doc.getElementsByTagName("Notaries").item(0);
        //	dvc.setIdAttributeNS(notariesElem, "", "Id");
        //	notariesElem.setIdAttributeNS("", "Id", true);

        XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);

        assertEquals(sig, sig2);
        assertTrue(sig2.validate(dvc));
    }

    private void dumpDocument(Document doc, Writer w) throws Exception {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        // trans.setOutputProperty(OutputKeys.INDENT, "yes");
        trans.transform(new DOMSource(doc), new StreamResult(w));
    }

    private void test_create_signature_external
        (SignatureMethod sm, KeyInfo ki, Key signingKey, KeySelector ks,
        boolean b64) throws Exception {

        // create reference
        Reference ref;
        if (b64) {
            ref = fac.newReference
                ("http://www.w3.org/Signature/2002/04/xml-stylesheet.b64",
                sha1, Collections.singletonList
                (fac.newTransform(Transform.BASE64,
                 (TransformParameterSpec) null)), null, null);
        } else {
            ref = fac.newReference
                ("http://www.w3.org/Signature/2002/04/xml-stylesheet.b64",sha1);
        }

        // create SignedInfo
        SignedInfo si = fac.newSignedInfo(withoutComments, sm,
            Collections.singletonList(ref));

        Document doc = XMLUtils.newDocument();

        // create XMLSignature
        XMLSignature sig = fac.newXMLSignature(si, ki);

        DOMSignContext dsc = new DOMSignContext(signingKey, doc);
        dsc.setURIDereferencer(ud);

        sig.sign(dsc);

        /*
        System.out.println("doc is:");
        StringWriter sw = new StringWriter();
        dumpDocument(doc, sw);
        System.out.println(sw.toString());
        */

        DOMValidateContext dvc = new DOMValidateContext
            (ks, doc.getDocumentElement());
        String base = System.getProperty("basedir") == null ? "./": System.getProperty("basedir");
        String fs = System.getProperty("file.separator");
        File f = new File(
            base + fs + "src/test/resources" + fs + "ie" + fs +
            "baltimore" + fs + "merlin-examples" + fs +
            "merlin-xmldsig-twenty-three" + fs);
        dvc.setBaseURI(f.toURI().toString());
        dvc.setURIDereferencer(ud);

        XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);

        assertEquals(sig, sig2);
        assertTrue(sig2.validate(dvc));
    }

    private void test_create_signature_enveloping
        (SignatureMethod sm, KeyInfo ki, Key signingKey, KeySelector ks,
        boolean b64) throws Exception {

        // create reference
        Reference ref;
        if (b64) {
            ref = fac.newReference("#object", sha1, Collections.singletonList
                (fac.newTransform(Transform.BASE64,
                 (TransformParameterSpec) null)), null, null);
        } else {
            ref = fac.newReference("#object", sha1);
        }

        // create SignedInfo
        SignedInfo si = fac.newSignedInfo(withoutComments, sm,
            Collections.singletonList(ref));

        Document doc = XMLUtils.newDocument();
        // create Objects
        XMLObject obj = fac.newXMLObject(Collections.singletonList
            (new DOMStructure(doc.createTextNode("some text"))),
            "object", null, null);

        // create XMLSignature
        XMLSignature sig = fac.newXMLSignature
            (si, ki, Collections.singletonList(obj), null, null);

        DOMSignContext dsc = new DOMSignContext(signingKey, doc);

        sig.sign(dsc);

        DOMValidateContext dvc = new DOMValidateContext
            (ks, doc.getDocumentElement());
        XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);

        assertEquals(sig, sig2);
        assertTrue(sig2.validate(dvc));
    }

}