package be.iminds.ilabt.jfed.util;

import org.apache.xml.security.Init;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.keys.storage.StorageResolver;
import org.apache.xml.security.keys.storage.implementations.KeyStoreResolver;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.utils.Constants;
import org.apache.xml.security.utils.ElementProxy;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.transform.TransformerException;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * XmlUtilTest
 *
 * @see be.iminds.ilabt.jfed.lowlevel.CredentialTests as well, which does a lot of xml signing and verification.
 */
public class XmlUtilTest {
    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(XmlUtilTest.class);

    /* Note: This cert and key pair is generated for tests only, they are used nowhere "real". */
    private static final String testPemPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\n" +
            "MIIEowIBAAKCAQEAt9DLTl6GDWg7RgCzepWyV9EpUfXUZUqQi1D8kJAWR5IcnyR1\n" +
            "wCt5BqfUR5uBtvn2m2XSz3nD0jT6+sGsx0G1+50h31ukOA1JnRlvgENNiJztio76\n" +
            "UP9eN0IrtFpuBK+g50kRrlrUhG/zfAV8snQpBO1Bue4YLJTf9mmnusTL2gWrzglG\n" +
            "MalOfbIU2H3yjfPh5es5VOVutvNXpGGKVYoJrlOZ1SgkKwhlt+ANyrj6+cERaVqb\n" +
            "gq1TeOOsFjdEq59HmP74eHTu0v9WrrWrlRbYElENbhDhGL2YXf0H9B+0eliTbkOl\n" +
            "y8ACIhGurjLKiPWIs6uKpaLLxcF0teQwsg0IFQIDAQABAoIBABacqsXjPt5bWh9M\n" +
            "asfDroK7Cjg4433qZEmfFtK5xuPbB4ZUN+AB+QtmjeiZKqXVrg6DwiEfu4UaW12J\n" +
            "gbWpUbe4JriRT2xNxiZ7QIoovVr24wnOeOCJ6Y8mprWzAiG1cTfCd1hZeBcqpms1\n" +
            "SZeyTnF6tkEnFvY1AjAP40BIgUM6hamTNPZgwRuob2ISHrLljm1AIOGRTY1hDISi\n" +
            "KpfyY7yHTZJLwfUQVD6KBLg9YeiGy1NPzE9UmXrQlRooiipLw/kGA6SAoUblqvS3\n" +
            "kFqTg/qUFxF4VxbCg4FjGXCQY4ws71OfGo4zgN/DmiO1vrHKnJvLIkjpTacMy2gr\n" +
            "PrhWWUECgYEA8pX9euSto87peYxYkDYnQXYAK65X4mFIOV8CYW6hXMbltS5z/1hW\n" +
            "dZKCNJr8ui6LpbcWTKmTYjDSxR15w+kuF1Trib682pQ2E3LCPYneBOJ0Hogv+D02\n" +
            "KF5PsCOYcReVwHq8H1dEck9j2g5wGLaajDWw3Vu7o3trT6zbUQD72YkCgYEAwfrc\n" +
            "RfKOk53HLSipM7Ipr+hPtYLrUExQTip8dh+3mAtXeMOe/Nm8P5ERSBAa8ETNx9fD                                                                                                                              \n" +
            "pzcQY/7GqgtLwAzgIM73yRSnUe0mDV4JwCeteJ8wpdB+xbPprPgp+4xj0oO0zfrh                                                                                                                              \n" +
            "9Gi7Wl9lsFHGz03WLcLks2JNk9yEbWdStIUFsy0CgYEA1wkaLwvy2BgcYkCEaSF3                                                                                                                              \n" +
            "3tEpCY98HBI8IY8U3yVgKIuvJ9JLxPebfJEollUk3i1QYM9RFxfiq9G3pD+ipoVW                                                                                                                              \n" +
            "9Bu0xt+rLN7gqJC7mi1R/2Z1pHL4gsZP8azYWrzS7r0HZB3oEKgc5m91hd/yghWs                                                                                                                              \n" +
            "HcmiRDaCuEI5N+F0b/O9THECgYAPqqARsiZbu7lzZz5LI4+EWoHdigZRROiTd5D3                                                                                                                              \n" +
            "xVYBnKDi6wGzMC6o/6FirZJPZ28rPbzai3LycIhBAYqLpz6Ox8hxYA6najzRhY/K                                                                                                                              \n" +
            "CipTfJ/kNHOYqhAsXRqe61bAkMyQeju3jqHbCatf0yr4YTP0HDJ2XnEfiQbVAyxF                                                                                                                              \n" +
            "0hyEvQKBgDOyK9omGnMAFTZOMUu94y+atccMqHyxCDLZl6yh9ipB+gvGTDh9c6+G\n" +
            "mMua/QVmH8yFT3NWM++2P54vuUFgrn3WmIpq4pkIoQ5qF9xi192oC7Kocwwy3OTn\n" +
            "lmyfwPhutAcGcMFZcQoNPXPzrCj1Ku4duXtO6jkWy3kTqvr8ib8j\n" +
            "-----END RSA PRIVATE KEY-----";
    private static final String testPemCert = "-----BEGIN CERTIFICATE-----\n" +
            "MIIEozCCA4ugAwIBAgIJAKdm6CkA/TLMMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD\n" +
            "VQQGEwJCRTETMBEGA1UECBMKU29tZS1TdGF0ZTEOMAwGA1UEBxMFR2hlbnQxDzAN\n" +
            "BgNVBAoTBmlNaW5kczEPMA0GA1UECxMGaWxhYi50MRQwEgYDVQQDEwtqRmVkIFRl\n" +
            "c3RlcjElMCMGCSqGSIb3DQEJARYWamZlZEBsaXN0cy5mZWQ0ZmlyZS5ldTAgFw0x\n" +
            "NDAzMjYwNzM1MThaGA8yMTUxMDIxNjA3MzUxOFowgZExCzAJBgNVBAYTAkJFMRMw\n" +
            "EQYDVQQIEwpTb21lLVN0YXRlMQ4wDAYDVQQHEwVHaGVudDEPMA0GA1UEChMGaU1p\n" +
            "bmRzMQ8wDQYDVQQLEwZpbGFiLnQxFDASBgNVBAMTC2pGZWQgVGVzdGVyMSUwIwYJ\n" +
            "KoZIhvcNAQkBFhZqZmVkQGxpc3RzLmZlZDRmaXJlLmV1MIIBIjANBgkqhkiG9w0B\n" +
            "AQEFAAOCAQ8AMIIBCgKCAQEAt9DLTl6GDWg7RgCzepWyV9EpUfXUZUqQi1D8kJAW\n" +
            "R5IcnyR1wCt5BqfUR5uBtvn2m2XSz3nD0jT6+sGsx0G1+50h31ukOA1JnRlvgENN\n" +
            "iJztio76UP9eN0IrtFpuBK+g50kRrlrUhG/zfAV8snQpBO1Bue4YLJTf9mmnusTL\n" +
            "2gWrzglGMalOfbIU2H3yjfPh5es5VOVutvNXpGGKVYoJrlOZ1SgkKwhlt+ANyrj6\n" +
            "+cERaVqbgq1TeOOsFjdEq59HmP74eHTu0v9WrrWrlRbYElENbhDhGL2YXf0H9B+0\n" +
            "eliTbkOly8ACIhGurjLKiPWIs6uKpaLLxcF0teQwsg0IFQIDAQABo4H5MIH2MB0G\n" +
            "A1UdDgQWBBSN6TiaD3UUm9aRBzS7fACP/+BZBDCBxgYDVR0jBIG+MIG7gBSN6Tia\n" +
            "D3UUm9aRBzS7fACP/+BZBKGBl6SBlDCBkTELMAkGA1UEBhMCQkUxEzARBgNVBAgT\n" +
            "ClNvbWUtU3RhdGUxDjAMBgNVBAcTBUdoZW50MQ8wDQYDVQQKEwZpTWluZHMxDzAN\n" +
            "BgNVBAsTBmlsYWIudDEUMBIGA1UEAxMLakZlZCBUZXN0ZXIxJTAjBgkqhkiG9w0B\n" +
            "CQEWFmpmZWRAbGlzdHMuZmVkNGZpcmUuZXWCCQCnZugpAP0yzDAMBgNVHRMEBTAD\n" +
            "AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQA/QKeMMXDvoWzPYmPhnQKro4Bk7YKd9HGk\n" +
            "rwQKAx2Qs/LLXV3pp6vYJ9t66XisfPZlz5l5L5uDzTdU98ugvrfdxCCPkPixFzty\n" +
            "tS1hbQXSc4V4Zv1tMy6cyKJOhzGR3t8f2tgn4kiBd6z1PaYci92f00/HuI8JQEYb\n" +
            "OzC63ZboIHyK14voKVomqXANqVlm+UdSjt8L+v5v1vxt/hIeDZQHwHcP9iTvuNT1\n" +
            "HZ47S38JUdX1vHU+YAMHetuBpDGOsM54OJT7IlXD140WNbgznydvhEDK9cZZhb7D\n" +
            "HJ/pNDUIkpUrhxlovpFi9rdhShOYL6XJEq4MlhDRNTM19qGRZIo9\n" +
            "-----END CERTIFICATE-----";
    private static final PrivateKey testPrivateKey;
    private static final PublicKey testPublicKey;
    private static final X509Certificate testCert;

    static {
        PrivateKey pk = null;
        X509Certificate c = null;
        try {
            pk = KeyUtil.pemToAnyPrivateKey(testPemPrivateKey, null);
            assert pk != null;
            c = KeyUtil.pemToX509Certificate(testPemCert);
            assert c != null;
        } catch (Exception e) {
            throw new RuntimeException("Static initialize of XmlUtilTest failed: " + e.getMessage(), e);
        }
        testPrivateKey = pk;
        testCert = c;
        testPublicKey = c.getPublicKey();
    }

    private boolean checkSig(String xmlString) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException {
        Document doc = XmlUtil.parseXmlFromStringMakeExceptionsRuntime(xmlString, true);
        XmlUtil.markXmlIdsAsXmlId(doc);
        return checkSig(doc);
    }

    private boolean checkSig(Document xmlDoc) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, "any_pass".toCharArray());
        trustStore.setCertificateEntry("testCert", testCert);

        assert xmlDoc != null; //initDoc should have been called

        NodeList signatureNodeList = xmlDoc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature");
        if (signatureNodeList.getLength() == 0) {
            LOG.debug("No Signature found in xml file: " + XmlUtil.elementToXmlString(xmlDoc.getDocumentElement()));
            return false;
        }
        LOG.debug("There are " + signatureNodeList.getLength() + " <signature> elements in <Signature> that need to be checked.");
        try {
            for (int i = 0; i < signatureNodeList.getLength(); i++) {
                Element sigElement = (Element) signatureNodeList.item(i);

                LOG.debug("Checking <signature> with apache santurio library");
                Init.init();

                ElementProxy.setDefaultPrefix(Constants.SignatureSpecNS, "");

                //Creates a XMLSignature from the element and uses the filename as
                //the baseURI. That URI is prepended to all relative URIs.
                XMLSignature signature =
                        new XMLSignature(sigElement, null);


                //Get the KeyInfo object, which might contain some clues as to what
                //key was used to create the signature. It might also contain the
                //full cert.
                KeyInfo ki = signature.getKeyInfo();

                ki.addStorageResolver(new StorageResolver(new KeyStoreResolver(trustStore)));

                if (ki != null) {
                    //First try to see if it is an X509Cert
                    X509Certificate cert =
                            signature.getKeyInfo().getX509Certificate();

                    if (cert != null) {
                        //check if the signature is valid using the cert
                        boolean check = signature.checkSignatureValue(cert);
                        LOG.debug("X509Certificate Check: " + check);
                        if (!check)
                            return false;
                    } else {
                        //Maybe it's a public key
                        PublicKey pk = signature.getKeyInfo().getPublicKey();
                        if (pk != null) {
                            //check if the signature is valid using the public key
                            boolean check = signature.checkSignatureValue(pk);
                            LOG.debug("PublicKey Check: " + check);
                            if (!check)
                                return false;
                        } else {
                            //No X509Cert or PublicKey could be found.
                            LOG.debug("Could not find Certificate or PublicKey");
                            return false;
                        }
                    }
                } else {
                    //If the signature did not contain any KeyInfo element
                    LOG.debug("Could not find ds:KeyInfo");
                    return false;
                }
            }
        } catch (Exception e) {
            //TODO: do we really want to catch all errors as validation failure?
            LOG.error("Error during checkSignedCredential", e);
            return false;
        }

        //if anything failed, it would have returned false above.
        return true;
    }

    @Test
    public void testXmlSign() throws TransformerException, XMLSecurityException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException {
        assert testCert != null;
        assert testPublicKey != null;
        assert testPrivateKey != null;

        String testXml = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>" +
                "<testxml>" +
                "   <test xml:id=\"id0\">" +
                "      <name>test</name>" +
                "      <foo>foo</foo>" +
                "   </test>" +
                "   <signatures></signatures>" +
                "</testxml>";
        Document doc = XmlUtil.parseXmlFromStringMakeExceptionsRuntime(testXml);
        XmlUtil.markXmlIdsAsXmlId(doc);
        String elementToSignId = "id0";
        String elementToAddSignatureToName = "signatures";

        String signedXml = XmlUtil.signXml(doc, elementToSignId, elementToAddSignatureToName, testCert, testPrivateKey);

        //not very useful to test if same
//        Assert.assertEquals(signedXml, java_signed_result);
//        Assert.assertEquals(signedXml, xmlsec1_signed_result);
        Assert.assertTrue(checkSig(signedXml));

        LOG.debug("testXmlSign() signedXml=\"" + signedXml + "\"");
    }

    @Test
    public void testParseXmlFromStringMakeExceptionsRuntime1() {
        Document doc = XmlUtil.parseXmlFromStringMakeExceptionsRuntime(simple_xml1);
        Assert.assertNotNull(doc.getDocumentElement());
        Assert.assertEquals(doc.getDocumentElement().getTagName(), "testxml");
    }

    @Test
    public void testParseXmlFromStringMakeExceptionsRuntime2() {
        Document doc = XmlUtil.parseXmlFromStringMakeExceptionsRuntime(
                "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>"+simple_xml1);
        Assert.assertNotNull(doc.getDocumentElement());
        Assert.assertEquals(doc.getDocumentElement().getTagName(), "testxml");
    }

    @Test
    public void testParseXmlFromStringMakeExceptionsRuntime3() {
        Document doc = XmlUtil.parseXmlFromStringMakeExceptionsRuntime(
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+simple_xml1);
        Assert.assertNotNull(doc.getDocumentElement());
        Assert.assertEquals(doc.getDocumentElement().getTagName(), "testxml");
    }

    @Test
    public void testParseXmlFromStringMakeExceptionsRuntime4() {
        Document doc = XmlUtil.parseXmlFromStringMakeExceptionsRuntime(java_signed_result);
        Assert.assertNotNull(doc.getDocumentElement());
        Assert.assertEquals(doc.getDocumentElement().getTagName(), "testxml");
    }


    @Test
    public void testCouldBeXmlVeryQuickTest() {
        Assert.assertTrue(XmlUtil.couldBeXmlVeryQuickTest(simple_xml1));
        Assert.assertTrue(XmlUtil.couldBeXmlVeryQuickTest(simple_xml2));
        Assert.assertTrue(XmlUtil.couldBeXmlVeryQuickTest(simple_xml3));
        Assert.assertTrue(XmlUtil.couldBeXmlVeryQuickTest(simple_xml4));
        Assert.assertTrue(XmlUtil.couldBeXmlVeryQuickTest(simple_xml5));
        Assert.assertTrue(XmlUtil.couldBeXmlVeryQuickTest(simple_xml6));
        Assert.assertTrue(XmlUtil.couldBeXmlVeryQuickTest(simple_xml7));
        Assert.assertTrue(XmlUtil.couldBeXmlVeryQuickTest(simple_xml8));

        Assert.assertFalse(XmlUtil.couldBeXmlVeryQuickTest(bad_xml1));
        Assert.assertFalse(XmlUtil.couldBeXmlVeryQuickTest("  " + simple_xml1));
        Assert.assertFalse(XmlUtil.couldBeXmlVeryQuickTest(" \n\t " + simple_xml1));
        //can't detect problem with the others
    }

    @Test
    public void testIsXmlLikeQuickTest() {
        Assert.assertTrue(XmlUtil.isXmlLikeQuickTest(simple_xml1));
        Assert.assertTrue(XmlUtil.isXmlLikeQuickTest(simple_xml2));
        Assert.assertTrue(XmlUtil.isXmlLikeQuickTest(simple_xml3));
        Assert.assertTrue(XmlUtil.isXmlLikeQuickTest(simple_xml4));
        Assert.assertTrue(XmlUtil.isXmlLikeQuickTest(simple_xml5));
        Assert.assertTrue(XmlUtil.isXmlLikeQuickTest(simple_xml6));
        Assert.assertTrue(XmlUtil.isXmlLikeQuickTest(simple_xml7));
        Assert.assertTrue(XmlUtil.isXmlLikeQuickTest(simple_xml8));

        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(bad_xml1));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest("  " + simple_xml1));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(" \n\t " + simple_xml1));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(bad_xml2));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(bad_xml4));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(bad_xml5));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(bad_xml6));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(bad_xml7));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(bad_xml8));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(bad_xml9));
        Assert.assertFalse(XmlUtil.isXmlLikeQuickTest(bad_xml10));

        //won't be able to detect problem here, and is not supposed to, as this test must be quick and thus incomplete
        Assert.assertTrue(XmlUtil.isXmlLikeQuickTest(bad_xml11));
    }

    @Test
    public void testIsWellFormedXmlQuickTest() {
        Assert.assertTrue(XmlUtil.isWellFormedXmlQuickTest(simple_xml1));
        Assert.assertTrue(XmlUtil.isWellFormedXmlQuickTest(simple_xml2));
        Assert.assertTrue(XmlUtil.isWellFormedXmlQuickTest(simple_xml3));
        Assert.assertTrue(XmlUtil.isWellFormedXmlQuickTest(simple_xml4));
        Assert.assertTrue(XmlUtil.isWellFormedXmlQuickTest(simple_xml5));
        Assert.assertTrue(XmlUtil.isWellFormedXmlQuickTest(simple_xml6));
        Assert.assertTrue(XmlUtil.isWellFormedXmlQuickTest(simple_xml7));
        Assert.assertTrue(XmlUtil.isWellFormedXmlQuickTest(simple_xml8));

        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml1));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest("  " + simple_xml1));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(" \n\t " + simple_xml1));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml2));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml4));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml5));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml6));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml7));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml8));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml9));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml10));
        Assert.assertFalse(XmlUtil.isWellFormedXmlQuickTest(bad_xml11));
    }



    private final String simple_xml1 = "<testxml><t>test</t><tt/></testxml>";
    private final String simple_xml2 = "<testxml/>";
    private final String simple_xml3 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<testxml><t>test</t><tt/></testxml>\n";
    private final String simple_xml4 = "<testxml>blablabla<bluh/>bla\nblabla</testxml>\n";
    private final String simple_xml5 = "<testxml><t>test</t><tt/></testxml>";
    private final String simple_xml6 = "<note><to>You</to><from>Me</from><subject>msg</subject><body>This is a test!</body></note>";
    private final String simple_xml7 = "<testxml att=\"blah\" y=\"blih\"><t>test</t><tt att=\"test\"/></testxml>";
    private final String simple_xml8 = "<ns:testxml xmlns:ns=\"http://test.com/test/\"><t>test</t><ns:tt/></ns:testxml>";

    private final String bad_xml1 = "blah<testxml><t>test</t><tt/></testxml>";
    private final String bad_xml2 = "<testxml <oops><t>test</t><tt/></testxml>";
    private final String bad_xml3 = "<testxml><t>test</t></><tt/></testxml>";
    private final String bad_xml4 = "<testxml><badnamespace:t>test</badnamespace:t></><tt/></testxml>";
    private final String bad_xml5 = "<ns:testxml xmlns:ns=\"http://test.com/test/\"><t>test</t><ns:tt/></testxml>";
    private final String bad_xml6 = "<testxml xmlns:ns=\"http://test.com/test/\"><t>test</t><ns:tt/></ns:testxml>";
    private final String bad_xml7 = "<testxml badatt=bad><t>test</t></><tt/></testxml>";
    private final String bad_xml8 = "<testxml><t>test</t></><tt badatt=bad/></testxml>";
    private final String bad_xml9 = "<testxml><t>test</t badatt=\"bad\"></><tt/></testxml>";
    private final String bad_xml10 = "<testxml><t>test</T></><tt/></testxml>";
    private final String bad_xml11 = "<testxml><tt/><tt/><tt/><tt/><tt/><tt/><tt/><tt/><tt/><tt/><tt/><t>test</T></><tt/></testxml>";

    //a java result that verifies with xmlsec1
    private final String java_signed_result =
            "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?><testxml>   <test xml:id=\"id0\">      <name>test</name>      <foo>foo</foo>   </test>   <signatures><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\" xml:id=\"Sig_id0\">\n" +
                    "<SignedInfo>\n" +
                    "<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n" +
                    "<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\n" +
                    "<Reference URI=\"#id0\">\n" +
                    "<Transforms>\n" +
                    "<Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/>\n" +
                    "<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n" +
                    "</Transforms>\n" +
                    "<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>\n" +
                    "<DigestValue>UiSQzKxdyW3WsDIlgxcaBD9K6UU=</DigestValue>\n" +
                    "</Reference>\n" +
                    "</SignedInfo>\n" +
                    "<SignatureValue>qAJyoT7hWTZUeVgSn47S39ZGczdjHzIW9t0bHnzPSHbkKUXQg/UO/xKYQHUrKYPYYd7jm+HDIWRX\n" +
                    "ElOxgD6kT/j16TAYBPq/iVVkJXnbLxn1++A9q82iH7Dg5Bjkh1jwCf9nWmjCKsIgyib0+yEHu89O\n" +
                    "CJOFAa2Jsc6RFJyQ3bcK7tKIF+YJQ/3IIpUnZWNxM1zBRmZUNx82bImTixU4ILUB7biJBQZiJHCd\n" +
                    "bns9F3c8KaCHxl/6xtqUppr6RPj6qhJF56zQxbcYPsMVkTjTL7juj6TWwAQIc2QN+MkmfNDawVN5\n" +
                    "2BZum6lhLSTdVrwcOYyfxUDGXNRiLjE8Tw/n0w==</SignatureValue>\n" +
                    "<KeyInfo>\n" +
                    "<X509Data>\n" +
                    "<X509Certificate>MIIEozCCA4ugAwIBAgIJAKdm6CkA/TLMMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYDVQQGEwJCRTET\n" +
                    "MBEGA1UECBMKU29tZS1TdGF0ZTEOMAwGA1UEBxMFR2hlbnQxDzANBgNVBAoTBmlNaW5kczEPMA0G\n" +
                    "A1UECxMGaWxhYi50MRQwEgYDVQQDEwtqRmVkIFRlc3RlcjElMCMGCSqGSIb3DQEJARYWamZlZEBs\n" +
                    "aXN0cy5mZWQ0ZmlyZS5ldTAgFw0xNDAzMjYwNzM1MThaGA8yMTUxMDIxNjA3MzUxOFowgZExCzAJ\n" +
                    "BgNVBAYTAkJFMRMwEQYDVQQIEwpTb21lLVN0YXRlMQ4wDAYDVQQHEwVHaGVudDEPMA0GA1UEChMG\n" +
                    "aU1pbmRzMQ8wDQYDVQQLEwZpbGFiLnQxFDASBgNVBAMTC2pGZWQgVGVzdGVyMSUwIwYJKoZIhvcN\n" +
                    "AQkBFhZqZmVkQGxpc3RzLmZlZDRmaXJlLmV1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\n" +
                    "AQEAt9DLTl6GDWg7RgCzepWyV9EpUfXUZUqQi1D8kJAWR5IcnyR1wCt5BqfUR5uBtvn2m2XSz3nD\n" +
                    "0jT6+sGsx0G1+50h31ukOA1JnRlvgENNiJztio76UP9eN0IrtFpuBK+g50kRrlrUhG/zfAV8snQp\n" +
                    "BO1Bue4YLJTf9mmnusTL2gWrzglGMalOfbIU2H3yjfPh5es5VOVutvNXpGGKVYoJrlOZ1SgkKwhl\n" +
                    "t+ANyrj6+cERaVqbgq1TeOOsFjdEq59HmP74eHTu0v9WrrWrlRbYElENbhDhGL2YXf0H9B+0eliT\n" +
                    "bkOly8ACIhGurjLKiPWIs6uKpaLLxcF0teQwsg0IFQIDAQABo4H5MIH2MB0GA1UdDgQWBBSN6Tia\n" +
                    "D3UUm9aRBzS7fACP/+BZBDCBxgYDVR0jBIG+MIG7gBSN6TiaD3UUm9aRBzS7fACP/+BZBKGBl6SB\n" +
                    "lDCBkTELMAkGA1UEBhMCQkUxEzARBgNVBAgTClNvbWUtU3RhdGUxDjAMBgNVBAcTBUdoZW50MQ8w\n" +
                    "DQYDVQQKEwZpTWluZHMxDzANBgNVBAsTBmlsYWIudDEUMBIGA1UEAxMLakZlZCBUZXN0ZXIxJTAj\n" +
                    "BgkqhkiG9w0BCQEWFmpmZWRAbGlzdHMuZmVkNGZpcmUuZXWCCQCnZugpAP0yzDAMBgNVHRMEBTAD\n" +
                    "AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQA/QKeMMXDvoWzPYmPhnQKro4Bk7YKd9HGkrwQKAx2Qs/LL\n" +
                    "XV3pp6vYJ9t66XisfPZlz5l5L5uDzTdU98ugvrfdxCCPkPixFztytS1hbQXSc4V4Zv1tMy6cyKJO\n" +
                    "hzGR3t8f2tgn4kiBd6z1PaYci92f00/HuI8JQEYbOzC63ZboIHyK14voKVomqXANqVlm+UdSjt8L\n" +
                    "+v5v1vxt/hIeDZQHwHcP9iTvuNT1HZ47S38JUdX1vHU+YAMHetuBpDGOsM54OJT7IlXD140WNbgz\n" +
                    "nydvhEDK9cZZhb7DHJ/pNDUIkpUrhxlovpFi9rdhShOYL6XJEq4MlhDRNTM19qGRZIo9</X509Certificate>\n" +
                    "</X509Data>\n" +
                    "</KeyInfo>\n" +
                    "</Signature></signatures></testxml>";

    //same thing, but signed by xmlsec1
    private final String xmlsec1_signed_result = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n" +
            "<testxml>\n" +
            "   <test xml:id=\"id0\">\n" +
            "      <name>test</name>\n" +
            "      <foo>foo</foo>\n" +
            "   </test>\n" +
            "   <signatures>\n" +
            "<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\" xml:id=\"Sig_id0\">\n" +
            "<SignedInfo>\n" +
            "<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n" +
            "<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\n" +
            "<Reference>\n" +
            "<Transforms>\n" +
            "<Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/>\n" +
            "<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n" +
            "</Transforms>\n" +
            "<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>\n" +
            "<DigestValue>8yKbnyLb03JAVQJbiRw09uo/Ads=</DigestValue>\n" +
            "</Reference>\n" +
            "</SignedInfo>\n" +
            "<SignatureValue>TF547ZV8Yk1nse7r7GUoM0Ys8Hjr5zib/J47Tw8ApEZ2K57IbnzrGajiOXnTW/mI\n" +
            "XfdelmHVm4FDaIUuroD2L6TDKOkfjBiYeYOZ97+VVwOwk30aPRnobdYU39oflcsR\n" +
            "KeU4Pzc5delWDfqn/3Z7kaEW2WoMLtbOa0vEhwBts95lc1ODSX2b6f6iKrboen9f\n" +
            "8LdRblS+LTPvFeQ6NfEuFwBfLI5OG0LmM6Fk0/WU6m/P7OohUm3/7HUyrzzLD4OD\n" +
            "umb/e6UmadG1m8vxP91PwleLRph/biHAxNF12Zx3l0ZdIh9PEprEcC5H2gh5KuX4\n" +
            "JdIQ0x2Nm9eg6OxNcoCJnQ==</SignatureValue>\n" +
            "<KeyInfo>\n" +
            "<X509Data>\n" +
            "<X509Certificate>MIIEozCCA4ugAwIBAgIJAKdm6CkA/TLMMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD\n" +
            "VQQGEwJCRTETMBEGA1UECBMKU29tZS1TdGF0ZTEOMAwGA1UEBxMFR2hlbnQxDzAN\n" +
            "BgNVBAoTBmlNaW5kczEPMA0GA1UECxMGaWxhYi50MRQwEgYDVQQDEwtqRmVkIFRl\n" +
            "c3RlcjElMCMGCSqGSIb3DQEJARYWamZlZEBsaXN0cy5mZWQ0ZmlyZS5ldTAgFw0x\n" +
            "NDAzMjYwNzM1MThaGA8yMTUxMDIxNjA3MzUxOFowgZExCzAJBgNVBAYTAkJFMRMw\n" +
            "EQYDVQQIEwpTb21lLVN0YXRlMQ4wDAYDVQQHEwVHaGVudDEPMA0GA1UEChMGaU1p\n" +
            "bmRzMQ8wDQYDVQQLEwZpbGFiLnQxFDASBgNVBAMTC2pGZWQgVGVzdGVyMSUwIwYJ\n" +
            "KoZIhvcNAQkBFhZqZmVkQGxpc3RzLmZlZDRmaXJlLmV1MIIBIjANBgkqhkiG9w0B\n" +
            "AQEFAAOCAQ8AMIIBCgKCAQEAt9DLTl6GDWg7RgCzepWyV9EpUfXUZUqQi1D8kJAW\n" +
            "R5IcnyR1wCt5BqfUR5uBtvn2m2XSz3nD0jT6+sGsx0G1+50h31ukOA1JnRlvgENN\n" +
            "iJztio76UP9eN0IrtFpuBK+g50kRrlrUhG/zfAV8snQpBO1Bue4YLJTf9mmnusTL\n" +
            "2gWrzglGMalOfbIU2H3yjfPh5es5VOVutvNXpGGKVYoJrlOZ1SgkKwhlt+ANyrj6\n" +
            "+cERaVqbgq1TeOOsFjdEq59HmP74eHTu0v9WrrWrlRbYElENbhDhGL2YXf0H9B+0\n" +
            "eliTbkOly8ACIhGurjLKiPWIs6uKpaLLxcF0teQwsg0IFQIDAQABo4H5MIH2MB0G\n" +
            "A1UdDgQWBBSN6TiaD3UUm9aRBzS7fACP/+BZBDCBxgYDVR0jBIG+MIG7gBSN6Tia\n" +
            "D3UUm9aRBzS7fACP/+BZBKGBl6SBlDCBkTELMAkGA1UEBhMCQkUxEzARBgNVBAgT\n" +
            "ClNvbWUtU3RhdGUxDjAMBgNVBAcTBUdoZW50MQ8wDQYDVQQKEwZpTWluZHMxDzAN\n" +
            "BgNVBAsTBmlsYWIudDEUMBIGA1UEAxMLakZlZCBUZXN0ZXIxJTAjBgkqhkiG9w0B\n" +
            "CQEWFmpmZWRAbGlzdHMuZmVkNGZpcmUuZXWCCQCnZugpAP0yzDAMBgNVHRMEBTAD\n" +
            "AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQA/QKeMMXDvoWzPYmPhnQKro4Bk7YKd9HGk\n" +
            "rwQKAx2Qs/LLXV3pp6vYJ9t66XisfPZlz5l5L5uDzTdU98ugvrfdxCCPkPixFzty\n" +
            "tS1hbQXSc4V4Zv1tMy6cyKJOhzGR3t8f2tgn4kiBd6z1PaYci92f00/HuI8JQEYb\n" +
            "OzC63ZboIHyK14voKVomqXANqVlm+UdSjt8L+v5v1vxt/hIeDZQHwHcP9iTvuNT1\n" +
            "HZ47S38JUdX1vHU+YAMHetuBpDGOsM54OJT7IlXD140WNbgznydvhEDK9cZZhb7D\n" +
            "HJ/pNDUIkpUrhxlovpFi9rdhShOYL6XJEq4MlhDRNTM19qGRZIo9</X509Certificate>\n" +
            "</X509Data>\n" +
            "</KeyInfo>\n" +
            "</Signature>\n" +
            "   </signatures>\n" +
            "</testxml>";
}
