/**
 * 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.
 */
package org.apache.xml.security.test.stax.encryption;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.dom.DOMSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.xml.security.encryption.EncryptedData;
import org.apache.xml.security.encryption.EncryptedKey;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.stax.ext.InboundXMLSec;
import org.apache.xml.security.stax.ext.OutboundXMLSec;
import org.apache.xml.security.stax.ext.SecurePart;
import org.apache.xml.security.stax.ext.XMLSec;
import org.apache.xml.security.stax.ext.XMLSecurityConstants;
import org.apache.xml.security.stax.ext.XMLSecurityProperties;
import org.apache.xml.security.test.dom.DSNamespaceContext;
import org.apache.xml.security.test.stax.signature.TestSecurityEventListener;
import org.apache.xml.security.test.stax.utils.StAX2DOM;
import org.apache.xml.security.test.stax.utils.XMLSecEventAllocator;
import org.apache.xml.security.test.stax.utils.XmlReaderToWriter;
import org.apache.xml.security.utils.XMLUtils;
import org.junit.Assert;
import org.junit.Before;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 */
public class XMLEncryption11Test extends Assert {

    private String cardNumber;
    private int nodeCount;

    private XMLInputFactory xmlInputFactory;

    @Before
    public void setUp() throws Exception {

        org.apache.xml.security.Init.init();

        xmlInputFactory = XMLInputFactory.newInstance();
        xmlInputFactory.setEventAllocator(new XMLSecEventAllocator());

        String filename = "org/w3c/www/interop/xmlenc-core-11/plaintext.xml";
        DocumentBuilder db = XMLUtils.createDocumentBuilder(false);
        Document doc = db.parse(this.getClass().getClassLoader().getResourceAsStream(filename));

        cardNumber = retrieveCCNumber(doc);
        nodeCount = countNodes(doc);
    }

    /**
     * rsa-oaep-mgf1p, Digest:SHA256, MGF:SHA1, PSource: None
     */
    @org.junit.Test
    public void testKeyWrappingRSA2048Outbound() throws Exception {
        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-2048_SHA256WithRSA.jks";
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();

        String filename = "org/w3c/www/interop/xmlenc-core-11/cipherText__RSA-2048__aes128-gcm__rsa-oaep-mgf1p.xml";

        Document dd = decryptElement(filename, rsaKey);
        checkDecryptedDoc(dd, true);
    }

    /**
     * rsa-oaep-mgf1p, Digest:SHA256, MGF:SHA1, PSource: None
     */
    @org.junit.Test
    public void testKeyWrappingRSA2048EncryptDecrypt() throws Exception {
        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-2048_SHA256WithRSA.jks";
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();
        X509Certificate x509Certificate = (X509Certificate) pkEntry.getCertificate();

        // Perform encryption
        String filename = "org/w3c/www/interop/xmlenc-core-11/plaintext.xml";

        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        keygen.init(256);
        SecretKey sessionKey = keygen.generateKey();

        SecurePart securePart =
                new SecurePart(new QName("urn:example:po", "PurchaseOrder"), SecurePart.Modifier.Element);

        Document ed = encryptDocument(filename, securePart, x509Certificate.getPublicKey(),
                "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p", null, null,
                sessionKey, "http://www.w3.org/2009/xmlenc11#aes128-gcm",
                null);
        // XMLUtils.outputDOM(ed.getFirstChild(), System.out);

        // Perform decryption
        Document dd = decryptElement(ed, rsaKey);
        // XMLUtils.outputDOM(dd.getFirstChild(), System.out);
        checkDecryptedDoc(dd, true);
    }

    /**
     * rsa-oaep-mgf1p, Digest:SHA256, MGF:SHA1, PSource: None
     */
    @org.junit.Test
    public void testKeyWrappingRSA3072() throws Exception {
        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-3072_SHA256WithRSA.jks";
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();

        // Perform encryption
        String filename = "org/w3c/www/interop/xmlenc-core-11/cipherText__RSA-3072__aes192-gcm__rsa-oaep-mgf1p__Sha256.xml";

        Document dd = decryptElement(filename, rsaKey);
        checkDecryptedDoc(dd, true);
    }

    /**
     * rsa-oaep-mgf1p, Digest:SHA256, MGF:SHA1, PSource: None
     */
    @org.junit.Test
    public void testKeyWrappingRSA3072EncryptDecrypt() throws Exception {
        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-3072_SHA256WithRSA.jks";
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();
        X509Certificate x509Certificate = (X509Certificate) pkEntry.getCertificate();

        // Perform encryption
        String filename = "org/w3c/www/interop/xmlenc-core-11/plaintext.xml";

        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        keygen.init(256);
        SecretKey sessionKey = keygen.generateKey();

        SecurePart securePart =
                new SecurePart(new QName("urn:example:po", "PurchaseOrder"), SecurePart.Modifier.Element);

        Document ed = encryptDocument(filename, securePart,
                x509Certificate.getPublicKey(), "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p",
                "http://www.w3.org/2001/04/xmlenc#sha256",
                null,
                sessionKey, "http://www.w3.org/2009/xmlenc11#aes192-gcm",
                null);
        // XMLUtils.outputDOM(ed.getFirstChild(), System.out);

        // Perform decryption
        Document dd = decryptElement(ed, rsaKey);
        // XMLUtils.outputDOM(dd.getFirstChild(), System.out);
        checkDecryptedDoc(dd, true);
    }

    /**
     * rsa-oaep, Digest:SHA384, MGF:SHA1, PSource: None
     */
    @org.junit.Test
    public void testKeyWrappingRSA3072OAEP() throws Exception {
        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-3072_SHA256WithRSA.jks";
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();

        String filename = "org/w3c/www/interop/xmlenc-core-11/cipherText__RSA-3072__aes256-gcm__rsa-oaep__Sha384-MGF_Sha1.xml";

        Document dd = decryptElement(filename, rsaKey);
        // XMLUtils.outputDOM(dd.getFirstChild(), System.out);
        checkDecryptedDoc(dd, true);
    }

    /**
     * rsa-oaep, Digest:SHA384, MGF:SHA1, PSource: None
     */
    @org.junit.Test
    public void testKeyWrappingRSA3072OAEPEncryptDecrypt() throws Exception {
        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-3072_SHA256WithRSA.jks";
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();
        X509Certificate x509Certificate = (X509Certificate) pkEntry.getCertificate();

        // Perform encryption
        String filename = "org/w3c/www/interop/xmlenc-core-11/plaintext.xml";

        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        keygen.init(256);
        SecretKey sessionKey = keygen.generateKey();

        SecurePart securePart =
                new SecurePart(new QName("urn:example:po", "PurchaseOrder"), SecurePart.Modifier.Element);

        Document ed = encryptDocument(filename, securePart,
                x509Certificate.getPublicKey(), "http://www.w3.org/2009/xmlenc11#rsa-oaep",
                "http://www.w3.org/2001/04/xmldsig-more#sha384",
                "http://www.w3.org/2009/xmlenc11#mgf1sha1",
                sessionKey, "http://www.w3.org/2009/xmlenc11#aes256-gcm",
                null);
        // XMLUtils.outputDOM(ed.getFirstChild(), System.out);

        // Perform decryption
        Document dd = decryptElement(ed, rsaKey);
        // XMLUtils.outputDOM(dd.getFirstChild(), System.out);
        checkDecryptedDoc(dd, true);
    }

    /**
     * rsa-oaep, Digest:SHA512, MGF:SHA1, PSource: Specified 8 bytes
     */
    @org.junit.Test
    public void testKeyWrappingRSA4096() throws Exception {
        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-4096_SHA256WithRSA.jks";
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();

        String filename = "org/w3c/www/interop/xmlenc-core-11/cipherText__RSA-4096__aes256-gcm__rsa-oaep__Sha512-MGF_Sha1_PSource.xml";

        Document dd = decryptElement(filename, rsaKey);
        // XMLUtils.outputDOM(dd.getFirstChild(), System.out);
        checkDecryptedDoc(dd, true);
    }

    /**
     * rsa-oaep, Digest:SHA512, MGF:SHA1, PSource: Specified 8 bytes
     */
    @org.junit.Test
    public void testKeyWrappingRSA4096EncryptDecrypt() throws Exception {
        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-4096_SHA256WithRSA.jks";

        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();
        X509Certificate x509Certificate = (X509Certificate) pkEntry.getCertificate();

        // Perform encryption
        String filename = "org/w3c/www/interop/xmlenc-core-11/plaintext.xml";

        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        keygen.init(256);
        SecretKey sessionKey = keygen.generateKey();

        SecurePart securePart =
                new SecurePart(new QName("urn:example:po", "PurchaseOrder"), SecurePart.Modifier.Element);

        Document ed = encryptDocument(filename, securePart,
                x509Certificate.getPublicKey(), "http://www.w3.org/2009/xmlenc11#rsa-oaep",
                "http://www.w3.org/2001/04/xmlenc#sha512",
                "http://www.w3.org/2009/xmlenc11#mgf1sha1",
                sessionKey, "http://www.w3.org/2009/xmlenc11#aes256-gcm",
                XMLUtils.decode("ZHVtbXkxMjM=".getBytes(StandardCharsets.UTF_8)));
        // XMLUtils.outputDOM(ed.getFirstChild(), System.out);

        // Perform decryption
        Document dd = decryptElement(ed, rsaKey);
        // XMLUtils.outputDOM(dd.getFirstChild(), System.out);
        checkDecryptedDoc(dd, true);
    }

    /**
     * rsa-oaep, Digest:SHA512, MGF:SHA512, PSource: Specified 8 bytes
     */
    @org.junit.Test
    public void testKeyWrappingRSA4096MGFSHA512EncryptDecrypt() throws Exception {
        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-4096_SHA256WithRSA.jks";

        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();
        X509Certificate x509Certificate = (X509Certificate) pkEntry.getCertificate();

        // Perform encryption
        String filename = "org/w3c/www/interop/xmlenc-core-11/plaintext.xml";

        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        keygen.init(256);
        SecretKey sessionKey = keygen.generateKey();

        SecurePart securePart =
                new SecurePart(new QName("urn:example:po", "PurchaseOrder"), SecurePart.Modifier.Element);

        Document ed = encryptDocument(filename, securePart,
                x509Certificate.getPublicKey(), "http://www.w3.org/2009/xmlenc11#rsa-oaep",
                "http://www.w3.org/2001/04/xmlenc#sha512",
                "http://www.w3.org/2009/xmlenc11#mgf1sha512",
                sessionKey, "http://www.w3.org/2009/xmlenc11#aes256-gcm",
                XMLUtils.decode("ZHVtbXkxMjM=".getBytes(StandardCharsets.UTF_8)));
        // XMLUtils.outputDOM(ed.getFirstChild(), System.out);

        // Perform decryption
        Document dd = decryptElement(ed, rsaKey);
        // XMLUtils.outputDOM(dd.getFirstChild(), System.out);
        checkDecryptedDoc(dd, true);
    }

    /**
     * rsa-oaep, Digest:SHA512, MGF:SHA512, PSource: Specified 8 bytes
     */
    @org.junit.Test
    public void testAESGCMAuthentication() throws Exception {

        String keystore = "org/w3c/www/interop/xmlenc-core-11/RSA-4096_SHA256WithRSA.jks";

        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(this.getClass().getClassLoader().getResourceAsStream(keystore), "passwd".toCharArray());

        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry("importkey", new KeyStore.PasswordProtection("passwd".toCharArray()));
        PrivateKey rsaKey = pkEntry.getPrivateKey();
        X509Certificate x509Certificate = (X509Certificate) pkEntry.getCertificate();

        // Perform encryption
        String filename = "org/w3c/www/interop/xmlenc-core-11/plaintext.xml";

        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        keygen.init(256);
        SecretKey sessionKey = keygen.generateKey();

        SecurePart securePart =
                new SecurePart(new QName("urn:example:po", "PurchaseOrder"), SecurePart.Modifier.Element);

        Document ed = encryptDocument(filename, securePart,
                x509Certificate.getPublicKey(), "http://www.w3.org/2009/xmlenc11#rsa-oaep",
                "http://www.w3.org/2001/04/xmlenc#sha512",
                "http://www.w3.org/2009/xmlenc11#mgf1sha512",
                sessionKey, "http://www.w3.org/2009/xmlenc11#aes256-gcm",
                XMLUtils.decode("ZHVtbXkxMjM=".getBytes(StandardCharsets.UTF_8)));
        // XMLUtils.outputDOM(ed.getFirstChild(), System.out);

        NodeList nl = ed.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#", "CipherValue");
        Element cipherValue = (Element) nl.item(1);
        String elementText = cipherValue.getTextContent();
        elementText = elementText.substring(0, 100) + 0 + elementText.substring(100);
        cipherValue.setTextContent(elementText);

        // Perform decryption
        try {
            decryptElementStAX(ed, rsaKey);
            Assert.fail("Exception expected");
        } catch (XMLStreamException e) {
            Assert.assertTrue(e.getCause() instanceof IOException);
            Assert.assertTrue(e.getCause().getCause() instanceof BadPaddingException);
            String cause = e.getCause().getCause().getMessage();
            Assert.assertTrue("mac check in GCM failed".equals(cause) || "Tag mismatch!".equals(cause));
        }
    }

    /**
     * Method decryptElement
     * <p></p>
     * Take a key, encryption type and a file, find an encrypted element
     * decrypt it and return the resulting document
     */
    private Document decryptElement(String filename, Key rsaKey) throws Exception {
        DocumentBuilder db = XMLUtils.createDocumentBuilder(false);
        Document doc = db.parse(this.getClass().getClassLoader().getResourceAsStream(filename));

        return decryptElement(doc, rsaKey);
    }

    /**
     * Method decryptElement
     * <p></p>
     * Take a key, encryption type and a document, find an encrypted element
     * decrypt it and return the resulting document
     */
    private Document decryptElement(Document doc, Key rsaKey) throws Exception {
        Document clonedDocument = (Document) doc.cloneNode(true);
        decryptElementDOM(doc, rsaKey);
        return decryptElementStAX(clonedDocument, rsaKey);
    }

    /**
     * Decrypt using StAX API
     */
    private Document decryptElementStAX(Document doc, Key rsaKey) throws Exception {
        XMLSecurityProperties properties = new XMLSecurityProperties();
        properties.setDecryptionKey(rsaKey);
        InboundXMLSec inboundXMLSec = XMLSec.getInboundWSSec(properties);
        TestSecurityEventListener securityEventListener = new TestSecurityEventListener();

        final XMLStreamReader xmlStreamReader =
                xmlInputFactory.createXMLStreamReader(new DOMSource(doc));

        XMLStreamReader securityStreamReader =
                inboundXMLSec.processInMessage(xmlStreamReader, null, securityEventListener);

        return StAX2DOM.readDoc(XMLUtils.createDocumentBuilder(false), securityStreamReader);
    }

    /**
     * Decrypt using DOM API
     */
    private Document decryptElementDOM(Document doc, Key rsaKey) throws Exception {

        // Create the XMLCipher element
        XMLCipher cipher = XMLCipher.getInstance();

        // Need to pre-load the Encrypted Data so we can get the key info
        Element ee =
                (Element) doc.getElementsByTagNameNS(
                        "http://www.w3.org/2001/04/xmlenc#", "EncryptedData"
                ).item(0);
        cipher.init(XMLCipher.DECRYPT_MODE, null);
        EncryptedData encryptedData = cipher.loadEncryptedData(doc, ee);

        KeyInfo ki = encryptedData.getKeyInfo();
        EncryptedKey encryptedKey = ki.itemEncryptedKey(0);

        XMLCipher cipher2 = XMLCipher.getInstance();
        cipher2.init(XMLCipher.UNWRAP_MODE, rsaKey);
        Key key =
                cipher2.decryptKey(
                        encryptedKey, encryptedData.getEncryptionMethod().getAlgorithm()
                );

        cipher.init(XMLCipher.DECRYPT_MODE, key);
        Document dd = cipher.doFinal(doc, ee);

        return dd;
    }

    /**
     * Encrypt a Document using the given parameters.
     */
    private Document encryptDocument(String filename, SecurePart securePart, Key encryptedKey, String encryptedKeyAlgo,
                                     String digestMethodAlgo, String mgfAlgo, Key sessionKey, String encryptionMethodAlgo,
                                     byte[] oaepParams)
            throws Exception {

        // Set up the Configuration
        XMLSecurityProperties properties = new XMLSecurityProperties();
        List<XMLSecurityConstants.Action> actions = new ArrayList<XMLSecurityConstants.Action>();
        actions.add(XMLSecurityConstants.ENCRYPT);
        properties.setActions(actions);

        properties.setEncryptionTransportKey(encryptedKey);
        properties.setEncryptionKeyTransportAlgorithm(encryptedKeyAlgo);
        properties.setEncryptionKeyTransportDigestAlgorithm(digestMethodAlgo);
        properties.setEncryptionKeyTransportMGFAlgorithm(mgfAlgo);
        properties.setEncryptionKeyTransportOAEPParams(oaepParams);

        properties.setEncryptionKey(sessionKey);
        properties.setEncryptionSymAlgorithm(encryptionMethodAlgo);

        properties.addEncryptionPart(securePart);

        OutboundXMLSec outboundXMLSec = XMLSec.getOutboundXMLSec(properties);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        XMLStreamWriter xmlStreamWriter = outboundXMLSec.processOutMessage(baos, StandardCharsets.UTF_8.name());

        InputStream sourceDocument =
                this.getClass().getClassLoader().getResourceAsStream(filename);
        XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);

        XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
        xmlStreamWriter.close();

        Document document = null;
        try (InputStream is = new ByteArrayInputStream(baos.toByteArray())) {
            document = XMLUtils.createDocumentBuilder(false).parse(is);
        }

        NodeList nodeList = document.getElementsByTagNameNS("urn:example:po", "PaymentInfo");
        Assert.assertEquals(nodeList.getLength(), 0);

        NodeList encryptionMethodElements = document.getElementsByTagNameNS(XMLSecurityConstants.NS_XMLENC, "EncryptionMethod");
        Assert.assertEquals(2, encryptionMethodElements.getLength());
        Assert.assertEquals(encryptionMethodAlgo, ((Element) encryptionMethodElements.item(0)).getAttribute("Algorithm"));
        Assert.assertEquals(encryptedKeyAlgo, ((Element) encryptionMethodElements.item(1)).getAttribute("Algorithm"));

        if (digestMethodAlgo != null) {
            NodeList digestMethodElements = document.getElementsByTagNameNS(XMLSecurityConstants.NS_DSIG, "DigestMethod");
            Assert.assertEquals(1, digestMethodElements.getLength());
            Assert.assertEquals(digestMethodAlgo, ((Element) digestMethodElements.item(0)).getAttribute("Algorithm"));
        }
        if (mgfAlgo != null) {
            NodeList mfgElements = document.getElementsByTagNameNS(XMLSecurityConstants.NS_XMLENC11, "MGF");
            Assert.assertEquals(1, mfgElements.getLength());
            Assert.assertEquals(mgfAlgo, ((Element) mfgElements.item(0)).getAttribute("Algorithm"));
        }
        if (oaepParams != null) {
            NodeList oaepParamsElements = document.getElementsByTagNameNS(XMLSecurityConstants.NS_XMLENC, "OAEPparams");
            Assert.assertEquals(1, oaepParamsElements.getLength());
            String content = XMLUtils.getFullTextChildrenFromNode(oaepParamsElements.item(0));
            Assert.assertArrayEquals(oaepParams, XMLUtils.decode(content));
        }
        return document;
    }


    /**
     * Method countNodes
     * <p></p>
     * Recursively count the number of nodes in the document
     *
     * @param n Node to count beneath
     */
    private static int countNodes(Node n) {

        if (n == null) {
            return 0;  // Paranoia
        }

        int count = 1;  // Always count myself
        Node c = n.getFirstChild();

        while (c != null) {
            count += countNodes(c);
            c = c.getNextSibling();
        }

        return count;
    }

    /**
     * Method retrieveCCNumber
     * <p></p>
     * Retrieve the credit card number from the payment info document
     *
     * @param doc The document to retrieve the card number from
     * @return The retrieved credit card number
     * @throws javax.xml.xpath.XPathExpressionException
     *
     */
    private static String retrieveCCNumber(Document doc)
            throws javax.xml.transform.TransformerException,
            XPathExpressionException {

        XPathFactory xpf = XPathFactory.newInstance();
        XPath xpath = xpf.newXPath();
        Map<String, String> namespace = new HashMap<>();
        namespace.put("x", "urn:example:po");
        DSNamespaceContext context = new DSNamespaceContext(namespace);
        xpath.setNamespaceContext(context);

        String expression = "//x:Number/text()";
        Node ccnumElt =
                (Node) xpath.evaluate(expression, doc, XPathConstants.NODE);

        if (ccnumElt != null) {
            return ccnumElt.getNodeValue();
        }

        return null;
    }

    /*
     * Check we have retrieved a Credit Card number and that it is OK
     * Check that the document has the correct number of nodes
     */
    private void checkDecryptedDoc(Document d, boolean doNodeCheck) throws Exception {

        String cc = retrieveCCNumber(d);
        assertTrue(cc, cc != null && cc.equals(cardNumber));

        // Test cc numbers
        if (doNodeCheck) {
            int myNodeCount = countNodes(d);

            assertTrue(
                "Node count mismatches", myNodeCount > 0 && myNodeCount == nodeCount
            );
        }
    }
}
