/**
 * 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.wss4j.dom.components.crypto;

import org.apache.wss4j.common.util.SOAPUtil;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.common.KeystoreCallbackHandler;

import org.apache.wss4j.dom.engine.WSSecurityEngine;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoFactory;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.util.KeyUtils;
import org.apache.wss4j.common.util.XMLUtils;
import org.apache.wss4j.dom.message.WSSecEncrypt;
import org.apache.wss4j.dom.message.WSSecHeader;
import org.apache.wss4j.dom.message.WSSecSignature;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.parsers.DocumentBuilderFactory;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

/**
 * This is a test for WSS-86 - "CryptoBase.splitAndTrim does not take into account the format of a
 * DN constructed by different providers":
 * http://issues.apache.org/jira/browse/WSS-86
 *
 * Keystore: keys\wss86.keystore
 * Password: security
 * Generated by:
 *
 * keytool -genkey -validity 3650 -alias wss86 -keyalg RSA -keystore wss86.keystore
 * -dname "1.2.840.113549.1.9.1=#16125765726e6572406578616d706c652e636f6d,CN=Werner,
 * OU=WSS4J,O=Apache,L=Munich,ST=Bayern,C=DE"
 */
public class CryptoProviderTest {
    private static final org.slf4j.Logger LOG =
        org.slf4j.LoggerFactory.getLogger(CryptoProviderTest.class);
    private WSSecurityEngine secEngine = new WSSecurityEngine();
    private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
    private Crypto crypto;

    public CryptoProviderTest() throws Exception {
        secEngine.getWssConfig(); //make sure BC gets registered
        crypto = CryptoFactory.getInstance("wss86.properties");
    }

    /**
     * Test signing a SOAP message using a cert with an OID
     */
    @Test
    public void testSignatureOID() throws Exception {
        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
        WSSecHeader secHeader = new WSSecHeader(doc);
        secHeader.insertSecurityHeader();

        WSSecSignature sign = new WSSecSignature(secHeader);
        sign.setUserInfo("wss86", "security");
        sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);

        Document signedDoc = sign.build(crypto);

        if (LOG.isDebugEnabled()) {
            String outputString =
                XMLUtils.prettyDocumentToString(signedDoc);
            LOG.debug(outputString);
        }
        verify(signedDoc);
    }

    /**
     * Like before but substitute in an "EMAILADDRESS" instead of the OID
     * @throws Exception
     */
    @Test
    public void testSignatureEmailAddress() throws Exception {
        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
        WSSecHeader secHeader = new WSSecHeader(doc);
        secHeader.insertSecurityHeader();

        WSSecSignature sign = new WSSecSignature(secHeader);
        sign.setUserInfo("wss86", "security");
        sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);

        Document signedDoc = sign.build(crypto);

        String outputString = XMLUtils.prettyDocumentToString(signedDoc);
        outputString =
            outputString.replace("1.2.840.113549.1.9.1=#16125765726e6572406578616d706c652e636f6d",
                             "EMAILADDRESS=Werner@example.com");

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        InputStream is = new ByteArrayInputStream(outputString.getBytes());
        Document parsedDoc = dbf.newDocumentBuilder().parse(is);
        verify(parsedDoc);
    }

    /**
     * Like before but substitute in an "E" instead of the OID
     * @throws Exception
     */
    @Test
    public void testSignatureOtherEmailAddress() throws Exception {
        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
        WSSecHeader secHeader = new WSSecHeader(doc);
        secHeader.insertSecurityHeader();

        WSSecSignature sign = new WSSecSignature(secHeader);
        sign.setUserInfo("wss86", "security");
        sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);

        Document signedDoc = sign.build(crypto);

        String outputString = XMLUtils.prettyDocumentToString(signedDoc);
        outputString =
            outputString.replace("1.2.840.113549.1.9.1=#16125765726e6572406578616d706c652e636f6d",
                             "E=Werner@example.com");

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        InputStream is = new ByteArrayInputStream(outputString.getBytes());
        Document parsedDoc = dbf.newDocumentBuilder().parse(is);
        verify(parsedDoc);
    }

    /**
     * Test loading a certificate using BouncyCastle, and using it to encrypt a message, but
     * decrypt the message using the Java Keystore provider
     */
    @Test
    public void testInterop() throws Exception {
        //
        // This cert corresponds to the cert in wss86.keystore
        // Extracted with:
        // keytool -export -rfc -keystore wss86.keystore -alias wss86 -file wss86.cer
        //
        byte[] certBytes =
            org.apache.xml.security.utils.XMLUtils.decode(
                "MIIDqTCCApGgAwIBAgIEePiYTTANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCREUxDzANBgNV"
                + "BAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNVBAsTBVdT"
                + "UzRKMQ8wDQYDVQQDEwZXZXJuZXIxITAfBgkqhkiG9w0BCQEWEldlcm5lckBleGFtcGxlLmNvbTAe"
                + "Fw0xNTA5MDkxNTA3MzFaFw0yNTA5MDYxNTA3MzFaMIGEMQswCQYDVQQGEwJERTEPMA0GA1UECBMG"
                + "QmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDzANBgNVBAoTBkFwYWNoZTEOMAwGA1UECxMFV1NTNEox"
                + "DzANBgNVBAMTBldlcm5lcjEhMB8GCSqGSIb3DQEJARYSV2VybmVyQGV4YW1wbGUuY29tMIIBIjAN"
                + "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoUlwwKbNU0vNPwEc32E85k36n7cWAmuuhpX+CoTk"
                + "XOfvpyoVcwBI8LwMmT1CR9KPxa+zmcE7RmX5qzVaW7Ukzra/pfD7YC3WGGAU9Awsq5OFLsMc4tZ/"
                + "7FM5azGdZA/wSI2384Ytnu88Z8O1qnBblLdNluNWVADq5tvgAdPQMoks9Xg+9SBiwj2p3C0RD0uM"
                + "x0bwscNEDWeHUJeGqNbWzEeYCvFLDGdl1Or3uha+drq4fNoVGstybM0VeGvFjP3NEX8dfl9WTxAl"
                + "3dB0TXzb70RuQghLqHJtDEXMC/ckaNHht6F/VcOxjZCtpLlMUptyPjrMDFOIaZ5q/6NSiMIjqwID"
                + "AQABoyEwHzAdBgNVHQ4EFgQUviIg1rtoiwto4gYIAWFHCsCDISkwDQYJKoZIhvcNAQELBQADggEB"
                + "AJEaMtEBpI7X1lx2+Wcjn2a3xugfTGZcy3s4fxGpbCxcdbDS7gWR/N+acwp4GXEbDrObwxIO/Kt5"
                + "eMzfD5EPCuMdLfLjK+G27RXc/89bR3aphm6ZyLnTLBJ5h24Of9+uDKY2bVIcF62uyXCnVAoq6dY/"
                + "rBj7btSjAOWFshMDJGNN7k/78s33sTdJfD2NQDvAvRZb1hYiUGcUij0ka+bhS/EtazH411w2NOQY"
                + "UyZ50HRroKJx1PPCE+OTO5JYPNQB2rauK63RHGGC94mY2ySCE2KP/yaWhkDJ60X2JKgnTLKUZxLP"
                + "9IioeHVeUzGIccIicoiZR5kqaiqoEk82V81R+VA="
            );

        try {
            Security.addProvider(new BouncyCastleProvider());
            CertificateFactory factory =
                CertificateFactory.getInstance("X.509", "BC");
            X509Certificate cert =
                (X509Certificate)factory.generateCertificate(
                    new ByteArrayInputStream(certBytes)
                );

            Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
            WSSecHeader secHeader = new WSSecHeader(doc);
            secHeader.insertSecurityHeader();

            WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
            encrypt.setUseThisCert(cert);

            KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
            SecretKey symmetricKey = keyGen.generateKey();
            Document encryptedDoc = encrypt.build(crypto, symmetricKey);

            if (LOG.isDebugEnabled()) {
                String outputString =
                    XMLUtils.prettyDocumentToString(encryptedDoc);
                LOG.debug(outputString);
            }
            verify(encryptedDoc);
        } finally {
            Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
        }

    }


    /**
     * Test loading a certificate using BouncyCastle, and using it to encrypt a message, but
     * decrypt the message using the Java Keystore provider. In this case though the cert doesn't
     * correspond with the cert in wss86.keystore.
     */
    @Test
    public void testBadInterop() throws Exception {
        byte[] certBytes =
            org.apache.xml.security.utils.XMLUtils.decode(
                "MIIDNDCCAp2gAwIBAgIBEDANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEPMA0GA1UECBMG"
                + "QmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUxFTATBgNVBAsTDEFwYWNoZSBX"
                + "U1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA4MDQwNDE5MzIxOFoXDTEwMDQwNDE5MzIxOFowYTEL"
                + "MAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZB"
                + "cGFjaGUxDjAMBgNVBAsTBVdTUzRKMQ8wDQYDVQQDEwZXZXJuZXIwgZ8wDQYJKoZIhvcNAQEBBQAD"
                + "gY0AMIGJAoGBAINlL3/k0H/zvknpBtLo8jzXwx/IJU/CGSv6MsqJZ2fyZ6kpLlXCuSBUZ/tfkdxp"
                + "uzhYq/Sc7A8csIk9gDf9RUbrhK0qKw0VP6DoCIJjS5IeN+NeJkx8YjmzLPmZqLYbNPXr/hy8CRrR"
                + "6CqLTTSkBwoEJ+cDkfZrdH2/bND0FEIZAgMBAAGjgfYwgfMwCQYDVR0TBAIwADAsBglghkgBhvhC"
                + "AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFSZXv0I5bG7XPEw"
                + "jylwG3lmZGdiMIGYBgNVHSMEgZAwgY2AFL/FsHHolGIMacU1TZW/88Bd2EL6oWqkaDBmMQswCQYD"
                + "VQQGEwJERTEPMA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx"
                + "FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkAuBIOAWJ19mwwDQYJKoZI"
                + "hvcNAQEEBQADgYEAUiUh/wORVcQYXxIh13h3w2Btg6Kj2g6V6YO0Utc/gEYWwT310C2OuroKAwwo"
                + "HapMIIWiJRclIAiA8Hnb0Sv/puuHYD4G4NWFdiVjRord90eZJe40NMGruRmlqIRIGGKCv+wv3E6U"
                + "x1cWW862f5H9Eyrcocke2P+3GNAGy83vghA="
            );

        try {
            Security.addProvider(new BouncyCastleProvider());
            CertificateFactory factory =
                CertificateFactory.getInstance("X.509", "BC");
            X509Certificate cert =
                (X509Certificate)factory.generateCertificate(
                    new ByteArrayInputStream(certBytes)
                );

            Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
            WSSecHeader secHeader = new WSSecHeader(doc);
            secHeader.insertSecurityHeader();

            WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
            encrypt.setUseThisCert(cert);

            KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
            SecretKey symmetricKey = keyGen.generateKey();
            Document encryptedDoc = encrypt.build(crypto, symmetricKey);

            if (LOG.isDebugEnabled()) {
                String outputString =
                    XMLUtils.prettyDocumentToString(encryptedDoc);
                LOG.debug(outputString);
            }
            try {
                verify(encryptedDoc);
                fail("Failure expected on encryption with a key that does not exist in the keystore");
            } catch (WSSecurityException ex) {
                assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILURE);
            }
        } finally {
            Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
        }
    }

    /**
     * Verifies the soap envelope
     * <p/>
     *
     * @param doc
     * @throws Exception Thrown when there is a problem in verification
     */
    private void verify(Document doc) throws Exception {
        secEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Verfied and decrypted message:");
            String outputString =
                XMLUtils.prettyDocumentToString(doc);
            LOG.debug(outputString);
        }
    }

}