/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.cryptolib.asymmetric.service;

import static junitparams.JUnitParamsRunner.$;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.Certificate;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.AfterClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;

import com.scytl.cryptolib.api.asymmetric.utils.KeyPairConverterAPI;
import com.scytl.cryptolib.api.exceptions.CryptoLibException;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.utils.AsymmetricTestDataGenerator;
import com.scytl.cryptolib.primitives.primes.utils.PrimitivesTestDataGenerator;
import com.scytl.cryptolib.primitives.securerandom.constants.SecureRandomConstants;
import com.scytl.cryptolib.test.tools.bean.TestCertificate;
import com.scytl.cryptolib.test.tools.bean.TestPrivateKey;
import com.scytl.cryptolib.test.tools.bean.TestPublicKey;
import com.scytl.cryptolib.test.tools.utils.CommonTestDataGenerator;

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;

/**
 * Tests of the asymmetric service API input validation.
 */
@RunWith(JUnitParamsRunner.class)
public class AsymmetricServiceValidationTest {

    static final private int MAXIMUM_DATA_ARRAY_LENGTH = 10;

    private static final String XML_FILES_TO_SIGN_PATH =
        "/data/xml_files_to_sign";

    private static final String SIGNED_XML_FILES_PATH =
        "target/signed_xml_files";

    private static final String SIGNED_XML_FILENAME_PREFIX = "signed_";

    private static final String XML_SIGNATURE_PARENT_NODE = "element1";

    private static AsymmetricService _asymmetricServiceForDefaultPolicy;

    private static String _whiteSpaceString;

    private static PublicKey _publicKeyForEncryption;

    private static PrivateKey _privateKeyForDecryption;

    private static PublicKey _publicKeyForVerification;

    private static PrivateKey _privateKeyForSigning;

    private static byte[] _data;

    private static byte[][] _dataArray;

    private static InputStream _dataInputStream;

    private static InputStream _xmlInputStream;

    private static OutputStream _signedXmlOutputStream;

    private static InputStream _signedXmlInputStream;

    private static byte[] _signature;

    private static KeyPairConverterAPI _keyPairConverter;

    private static byte[] _emptyByteArray;

    private static byte[][] _emptyByteArrayArray;

    private static TestPublicKey _nullContentPublicKey;

    private static TestPublicKey _emptyContentPublicKey;

    private static TestPrivateKey _nullContentPrivateKey;

    private static TestPrivateKey _emptyContentPrivateKey;

    private static byte[][] _dataArrayConsistingOfNullElement;

    private static byte[][] _dataArrayConsistingOfEmptyElement;

    private static byte[][] _dataArrayContainingNullElement;

    private static byte[][] _dataArrayContainingEmptyElement;

    private static PublicKey _illegalSizePublicKeyForEncryption;

    private static PrivateKey _illegalSizePrivateKeyForDecryption;

    private static PublicKey _illegalSizePublicKeyForVerification;

    private static PrivateKey _illegalSizePrivateKeyForSigning;

    static {
        try {
            setUp();
        } catch (GeneralCryptoLibException e) {
            throw new CryptoLibException("Setup failed for class "
                + AsymmetricServiceValidationTest.class.getSimpleName());
        }
    }

    public static void setUp() throws GeneralCryptoLibException {

        Security.addProvider(new BouncyCastleProvider());

        _asymmetricServiceForDefaultPolicy = new AsymmetricService();

        _whiteSpaceString =
            CommonTestDataGenerator
                .getWhiteSpaceString(CommonTestDataGenerator.getInt(1,
                    SecureRandomConstants.MAXIMUM_GENERATED_STRING_LENGTH));

        KeyPair keyPair =
            _asymmetricServiceForDefaultPolicy.getKeyPairForEncryption();
        _publicKeyForEncryption = keyPair.getPublic();
        _privateKeyForDecryption = keyPair.getPrivate();

        keyPair =
            _asymmetricServiceForDefaultPolicy.getKeyPairForSigning();
        _publicKeyForVerification = keyPair.getPublic();
        _privateKeyForSigning = keyPair.getPrivate();

        int dataByteLength =
            CommonTestDataGenerator.getInt(1,
                SecureRandomConstants.MAXIMUM_GENERATED_BYTE_ARRAY_LENGTH);

        _data = PrimitivesTestDataGenerator.getByteArray(dataByteLength);

        _dataArray =
            PrimitivesTestDataGenerator.getByteArrayArray(dataByteLength,
                CommonTestDataGenerator.getInt(2,
                    MAXIMUM_DATA_ARRAY_LENGTH));

        _dataInputStream = new ByteArrayInputStream(_data);

        _signature =
            _asymmetricServiceForDefaultPolicy.sign(_privateKeyForSigning,
                _dataArray);

        _keyPairConverter =
            _asymmetricServiceForDefaultPolicy.getKeyPairConverter();

        _emptyByteArray = new byte[0];
        _emptyByteArrayArray = new byte[0][0];

        _nullContentPublicKey = new TestPublicKey(null);
        _emptyContentPublicKey = new TestPublicKey(_emptyByteArray);

        _nullContentPrivateKey = new TestPrivateKey(null);
        _emptyContentPrivateKey = new TestPrivateKey(_emptyByteArray);

        _dataArrayConsistingOfNullElement = new byte[1][dataByteLength];
        _dataArrayConsistingOfNullElement[0] = null;

        _dataArrayConsistingOfEmptyElement = new byte[1][dataByteLength];
        _dataArrayConsistingOfEmptyElement[0] = _emptyByteArray;

        _dataArrayContainingNullElement = _dataArray.clone();
        _dataArrayContainingNullElement[0] = null;

        _dataArrayContainingEmptyElement = _dataArray.clone();
        _dataArrayContainingEmptyElement[0] = _emptyByteArray;

        keyPair =
            AsymmetricTestDataGenerator
                .getIllegaSizeKeyPairForEncryption();
        _illegalSizePublicKeyForEncryption = keyPair.getPublic();
        _illegalSizePrivateKeyForDecryption = keyPair.getPrivate();

        keyPair =
            AsymmetricTestDataGenerator.getIllegalSizeKeyPairForSigning();
        _illegalSizePublicKeyForVerification = keyPair.getPublic();
        _illegalSizePrivateKeyForSigning = keyPair.getPrivate();
    }

    @AfterClass
    public static void tearDown() {

        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
    }

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    @Parameters(method = "createAsymmetricService")
    public void testAsymmetricServiceCreationValidation(String path,
            String errorMsg) throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        new AsymmetricService(path);
    }

    public static Object[] createAsymmetricService() {

        return $($(null, "Properties file path is null."),
            $("", "Properties file path is blank."),
            $(_whiteSpaceString, "Properties file path is blank."));
    }

    @Test
    @Parameters(method = "asymmetricallyEncrypt")
    public void testAsymmetricEncryptionValidation(PublicKey key,
            byte[] data, String errorMsg) throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _asymmetricServiceForDefaultPolicy.encrypt(key, data);
    }

    public static Object[] asymmetricallyEncrypt() {

        return $(
            $(null, _data, "Public key is null."),
            $(_nullContentPublicKey, _data, "Public key content is null."),
            $(_emptyContentPublicKey, _data,
                "Public key content is empty."),
            $(_illegalSizePublicKeyForEncryption,
                _data,
                "Byte length of encryption public key must be equal to byte length of corresponding key in cryptographic policy for asymmetric service: "),
            $(_publicKeyForEncryption, null, "Data is null."),
            $(_publicKeyForEncryption, _emptyByteArray, "Data is empty."));
    }

    @Test
    @Parameters(method = "asymmetricallyDecrypt")
    public void testAsymmetricDecryptionValidation(PrivateKey key,
            byte[] data, String errorMsg) throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _asymmetricServiceForDefaultPolicy.decrypt(key, data);
    }

    public static Object[] asymmetricallyDecrypt() {

        return $(
            $(null, _data, "Private key is null."),
            $(_nullContentPrivateKey, _data,
                "Private key content is null."),
            $(_emptyContentPrivateKey, _data,
                "Private key content is empty."),
            $(_illegalSizePrivateKeyForDecryption,
                _data,
                "Byte length of decryption private key must be equal to byte length of corresponding key in cryptographic policy for asymmetric service: "),
            $(_privateKeyForDecryption, null, "Encrypted data is null."),
            $(_privateKeyForDecryption, _emptyByteArray,
                "Encrypted data is empty."));
    }

    @Test
    @Parameters(method = "sign")
    public void testSigningValidation(PrivateKey key, byte[][] data,
            String errorMsg) throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _asymmetricServiceForDefaultPolicy.sign(key, data);
    }

    public static Object[] sign() {

        return $(
            $(null, _dataArray, "Private key is null."),
            $(_nullContentPrivateKey, _dataArray,
                "Private key content is null."),
            $(_emptyContentPrivateKey, _dataArray,
                "Private key content is empty."),
            $(_illegalSizePrivateKeyForSigning,
                _dataArray,
                "Byte length of signing private key must be equal to byte length of corresponding key in cryptographic policy for asymmetric service: "),
            $(_privateKeyForSigning, null, "Data element array is null."),
            $(_privateKeyForSigning, _emptyByteArrayArray,
                "Data element array is empty."),
            $(_privateKeyForSigning, _dataArrayConsistingOfNullElement,
                "Data is null."),
            $(_privateKeyForSigning, _dataArrayConsistingOfEmptyElement,
                "Data is empty."),
            $(_privateKeyForSigning, _dataArrayContainingNullElement,
                "A data element is null."),
            $(_privateKeyForSigning, _dataArrayContainingEmptyElement,
                "A data element is empty."));
    }

    @Test
    @Parameters(method = "verifySignature")
    public void testSignatureVerificationValidation(byte[] signature,
            PublicKey key, byte[][] data, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _asymmetricServiceForDefaultPolicy.verifySignature(signature, key,
            data);
    }

    public static Object[] verifySignature() {

        return $(
            $(null, _publicKeyForVerification, _dataArray,
                "Signature is null."),
            $(_emptyByteArray, _publicKeyForVerification, _dataArray,
                "Signature is empty."),
            $(_signature, null, _dataArray, "Public key is null."),
            $(_signature, _nullContentPublicKey, _dataArray,
                "Public key content is null."),
            $(_signature, _emptyContentPublicKey, _dataArray,
                "Public key content is empty."),
            $(_signature,
                _illegalSizePublicKeyForVerification,
                _dataArray,
                "Byte length of signature verification public key must be equal to byte length of corresponding key in cryptographic policy for asymmetric service: "),
            $(_signature, _publicKeyForVerification, null,
                "Data element array is null."),
            $(_signature, _publicKeyForVerification, _emptyByteArrayArray,
                "Data element array is empty."),
            $(_signature, _publicKeyForVerification,
                _dataArrayConsistingOfNullElement, "Data is null."),
            $(_signature, _publicKeyForVerification,
                _dataArrayConsistingOfEmptyElement, "Data is empty."),
            $(_signature, _publicKeyForVerification,
                _dataArrayContainingNullElement, "A data element is null."),
            $(_signature, _publicKeyForVerification,
                _dataArrayContainingEmptyElement,
                "A data element is empty."));
    }

    @Test
    @Parameters(method = "signFromDataInputStream")
    public void testSigningFromDataInputStreamValidation(PrivateKey key,
            InputStream inStream, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _asymmetricServiceForDefaultPolicy.sign(key, inStream);
    }

    public static Object[] signFromDataInputStream() {

        return $(
            $(null, _dataInputStream, "Private key is null."),
            $(_nullContentPrivateKey, _dataInputStream,
                "Private key content is null."),
            $(_emptyContentPrivateKey, _dataInputStream,
                "Private key content is empty."),
            $(_illegalSizePrivateKeyForSigning,
                _dataInputStream,
                "Byte length of signing private key must be equal to byte length of corresponding key in cryptographic policy for asymmetric service: "),
            $(_privateKeyForSigning, null, "Data input stream is null."));
    }

    @Test
    @Parameters(method = "verifySignatureFromDataInputStream")
    public void testSignatureVerificationFromDataInputStreamValidation(
            byte[] signature, PublicKey key, InputStream inStream,
            String errorMsg) throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _asymmetricServiceForDefaultPolicy.verifySignature(signature, key,
            inStream);
    }

    public static Object[] verifySignatureFromDataInputStream() {

        return $(
            $(null, _publicKeyForVerification, _dataInputStream,
                "Signature is null."),
            $(_emptyByteArray, _publicKeyForVerification,
                _dataInputStream, "Signature is empty."),
            $(_signature, null, _dataInputStream, "Public key is null."),
            $(_signature, _nullContentPublicKey, _dataInputStream,
                "Public key content is null."),
            $(_signature, _emptyContentPublicKey, _dataInputStream,
                "Public key content is empty."),
            $(_signature,
                _illegalSizePublicKeyForVerification,
                _dataInputStream,
                "Byte length of signature verification public key must be equal to byte length of corresponding key in cryptographic policy for asymmetric service: "),
            $(_signature, _publicKeyForVerification, null,
                "Data input stream is null."));
    }

    @Test
    @Parameters(method = "signXml")
    public void testXmlSigningValidation(PrivateKey key,
            Certificate[] certChain, InputStream inStream,
            OutputStream outStream, String signatureParentNode,
            String errorMsg) throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _asymmetricServiceForDefaultPolicy.signXml(key, certChain,
            inStream, outStream, signatureParentNode);
    }

    public static Object[] signXml()
            throws FileNotFoundException, GeneralCryptoLibException,
            URISyntaxException {

        Certificate[] chainContainingNull = new Certificate[2];
        chainContainingNull[0] =
            new TestCertificate(TestCertificate.class.getSimpleName(),
                _publicKeyForEncryption);
        chainContainingNull[1] = null;

        Certificate[] chainContainingNullContentCert =
            chainContainingNull.clone();
        chainContainingNullContentCert[1] =
            new TestCertificate(TestCertificate.class.getSimpleName(),
                new TestPublicKey(null));

        Certificate[] chainContainingEmptyContentCert =
            chainContainingNull.clone();
        chainContainingEmptyContentCert[1] =
            new TestCertificate(TestCertificate.class.getSimpleName(),
                new TestPublicKey(_emptyByteArray));

        setUpXmlSignatureStreams();

        return $(
            $(null, null, _xmlInputStream, _signedXmlOutputStream,
                XML_SIGNATURE_PARENT_NODE, "Private key is null."),
            $(_nullContentPrivateKey, null, _xmlInputStream,
                _signedXmlOutputStream, XML_SIGNATURE_PARENT_NODE,
                "Private key content is null."),
            $(_emptyContentPrivateKey, null, _xmlInputStream,
                _signedXmlOutputStream, XML_SIGNATURE_PARENT_NODE,
                "Private key content is empty."),
            $(_illegalSizePrivateKeyForSigning,
                null,
                _xmlInputStream,
                _signedXmlOutputStream,
                XML_SIGNATURE_PARENT_NODE,
                "Byte length of XML signing private key must be equal to byte length of corresponding key in cryptographic policy for asymmetric service: "),
            $(_privateKeyForSigning, chainContainingNull, _xmlInputStream,
                _signedXmlOutputStream, XML_SIGNATURE_PARENT_NODE,
                "Certificate in chain is null."),
            $(_privateKeyForSigning, chainContainingNullContentCert,
                _xmlInputStream, _signedXmlOutputStream,
                XML_SIGNATURE_PARENT_NODE,
                "Content of certificate in chain is null."),
            $(_privateKeyForSigning, chainContainingEmptyContentCert,
                _xmlInputStream, _signedXmlOutputStream,
                XML_SIGNATURE_PARENT_NODE,
                "Content of certificate in chain is empty."),
            $(_privateKeyForSigning, null, null, _signedXmlOutputStream,
                XML_SIGNATURE_PARENT_NODE, "XML input stream is null."),
            $(_privateKeyForSigning, null, _xmlInputStream, null,
                XML_SIGNATURE_PARENT_NODE,
                "Signed XML output stream is null."),
            $(_privateKeyForSigning, null, _xmlInputStream,
                _signedXmlOutputStream, _whiteSpaceString,
                "XML signature parent node is blank."));
    }

    @Test
    @Parameters(method = "verifyXmlSignature")
    public void testXmlSignatureVerificationValidation(PublicKey key,
            InputStream inStream, String signatureParentNode,
            String errorMsg) throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _asymmetricServiceForDefaultPolicy.verifyXmlSignature(key,
            inStream, signatureParentNode);
    }

    public static Object[] verifyXmlSignature()
            throws FileNotFoundException, GeneralCryptoLibException,
            URISyntaxException {

        setUpXmlSignatureStreams();

        return $(
            $(null, _signedXmlInputStream, XML_SIGNATURE_PARENT_NODE,
                "Public key is null."),
            $(_nullContentPublicKey, _signedXmlInputStream,
                XML_SIGNATURE_PARENT_NODE, "Public key content is null."),
            $(_emptyContentPublicKey, _signedXmlInputStream,
                XML_SIGNATURE_PARENT_NODE, "Public key content is empty."),
            $(_illegalSizePublicKeyForVerification,
                _signedXmlInputStream,
                XML_SIGNATURE_PARENT_NODE,
                "Byte length of XML signature verification public key must be equal to byte length of corresponding key in cryptographic policy for asymmetric service: "),
            $(_publicKeyForVerification, null, XML_SIGNATURE_PARENT_NODE,
                "Signed XML input stream is null."),
            $(_publicKeyForVerification, _signedXmlInputStream,
                _whiteSpaceString, "XML signature parent node is blank."));
    }

    @Test
    @Parameters(method = "convertPublicKeyForEncryptionToPem")
    public void testPublicKeyForEncryptionConversionToPemValidation(
            PublicKey key, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _keyPairConverter.exportPublicKeyForEncryptingToPem(key);
    }

    public static Object[] convertPublicKeyForEncryptionToPem() {

        return $($(null, "Public key is null."),
            $(_nullContentPublicKey, "Public key content is null."),
            $(_emptyContentPublicKey, "Public key content is empty."));
    }

    @Test
    @Parameters(method = "convertPrivateKeyForEncryptionToPem")
    public void testPrivateKeyForEncryptionConversionToPemValidation(
            PrivateKey key, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _keyPairConverter.exportPrivateKeyForEncryptingToPem(key);
    }

    public static Object[] convertPrivateKeyForEncryptionToPem() {

        return $($(null, "Private key is null."),
            $(_nullContentPrivateKey, "Private key content is null."),
            $(_emptyContentPrivateKey, "Private key content is empty."));
    }

    @Test
    @Parameters(method = "getPublicKeyForEncryptionFromPem")
    public void testPublicKeyForEncryptionRetrievalFromPemValidation(
            String pemStr, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _keyPairConverter.getPublicKeyForEncryptingFromPem(pemStr);
    }

    public static Object[] getPublicKeyForEncryptionFromPem() {

        return $($(null, "Public key PEM string is null."),
            $("", "Public key PEM string is blank."),
            $(_whiteSpaceString, "Public key PEM string is blank."));
    }

    @Test
    @Parameters(method = "getPrivateKeyForEncryptionFromPem")
    public void testPrivateKeyForEncryptionRetrievalFromPemValidation(
            String pemStr, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _keyPairConverter.getPrivateKeyForEncryptingFromPem(pemStr);
    }

    public static Object[] getPrivateKeyForEncryptionFromPem() {

        return $($(null, "Private key PEM string is null."),
            $("", "Private key PEM string is blank."),
            $(_whiteSpaceString, "Private key PEM string is blank."));
    }

    @Test
    @Parameters(method = "convertPublicKeyForSigningToPem")
    public void testPublicKeyForSigningConversionToPemValidation(
            PublicKey key, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _keyPairConverter.exportPublicKeyForSigningToPem(key);
    }

    public static Object[] convertPublicKeyForSigningToPem() {

        return $($(null, "Public key is null."),
            $(_nullContentPublicKey, "Public key content is null."),
            $(_emptyContentPublicKey, "Public key content is empty."));
    }

    @Test
    @Parameters(method = "convertPrivateKeyForSigningToPem")
    public void testPrivateKeyForSigningConversionToPemValidation(
            PrivateKey key, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _keyPairConverter.exportPrivateKeyForSigningToPem(key);
    }

    public static Object[] convertPrivateKeyForSigningToPem() {

        return $($(null, "Private key is null."),
            $(_nullContentPrivateKey, "Private key content is null."),
            $(_emptyContentPrivateKey, "Private key content is empty."));
    }

    @Test
    @Parameters(method = "getPublicKeyForSigningFromPem")
    public void testPublicKeyForSigningRetrievalFromPemValidation(
            String pemStr, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _keyPairConverter.getPublicKeyForSigningFromPem(pemStr);
    }

    public static Object[] getPublicKeyForSigningFromPem() {

        return $($(null, "Public key PEM string is null."),
            $("", "Public key PEM string is blank."),
            $(_whiteSpaceString, "Public key PEM string is blank."));
    }

    @Test
    @Parameters(method = "getPrivateKeyForSigningFromPem")
    public void testGetPrivateKeyForSigningRetrievalFromPemValidation(
            String pemStr, String errorMsg)
            throws GeneralCryptoLibException {

        thrown.expect(GeneralCryptoLibException.class);
        thrown.expectMessage(errorMsg);
        _keyPairConverter.getPrivateKeyForEncryptingFromPem(pemStr);
    }

    public static Object[] getPrivateKeyForSigningFromPem() {

        return $($(null, "Private key PEM string is null."),
            $("", "Private key PEM string is blank."),
            $(_whiteSpaceString, "Private key PEM string is blank."));
    }

    private static void setUpXmlSignatureStreams()
            throws GeneralCryptoLibException, FileNotFoundException,
            URISyntaxException {

        File signedFilesDir = new File(SIGNED_XML_FILES_PATH);
        if (!signedFilesDir.exists()) {
            boolean dirCreated = signedFilesDir.mkdir();
            if (!dirCreated) {
                throw new GeneralCryptoLibException("Directory "
                    + SIGNED_XML_FILES_PATH + " could not be created.");
            }

        }

        File filesToSignDir =
            new File(AsymmetricServiceValidationTest.class.getResource(
                XML_FILES_TO_SIGN_PATH).toURI());
        File[] filesToSign = filesToSignDir.listFiles();
        if (filesToSign == null) {
            throw new GeneralCryptoLibException("Directory "
                + XML_FILES_TO_SIGN_PATH + " cannot be accessed.");
        } else if (filesToSign.length == 0) {
            throw new GeneralCryptoLibException("Directory "
                + XML_FILES_TO_SIGN_PATH + " contains no files to sign.");
        } else {
            File fileToSign = filesToSign[0];

            _xmlInputStream = new FileInputStream(fileToSign);

            _signedXmlOutputStream =
                new FileOutputStream(SIGNED_XML_FILES_PATH
                    + File.separatorChar + SIGNED_XML_FILENAME_PREFIX
                    + fileToSign.getName());

            _asymmetricServiceForDefaultPolicy.signXml(
                _privateKeyForSigning, null, _xmlInputStream,
                _signedXmlOutputStream, XML_SIGNATURE_PARENT_NODE);

            _signedXmlInputStream =
                new FileInputStream(SIGNED_XML_FILES_PATH
                    + File.separatorChar + "signed_"
                    + fileToSign.getName());
        }
    }
}
