/*
 * 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.digital.envelope.configuration;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.CryptoLibException;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.cipher.configuration.ConfigAsymmetricCipherAlgorithmAndSpec;
import com.scytl.cryptolib.asymmetric.keypair.configuration.ConfigEncryptionKeyPairAlgorithmAndSpec;
import com.scytl.cryptolib.commons.constants.Constants;
import com.scytl.cryptolib.commons.utils.system.OperatingSystem;
import com.scytl.cryptolib.primitives.securerandom.configuration.ConfigSecureRandomAlgorithmAndProvider;
import com.scytl.cryptolib.symmetric.cipher.configuration.ConfigSymmetricCipherAlgorithmAndSpec;
import com.scytl.cryptolib.symmetric.key.configuration.ConfigHmacSecretKeyAlgorithmAndSpec;
import com.scytl.cryptolib.symmetric.key.configuration.ConfigSecretKeyAlgorithmAndSpec;
import com.scytl.cryptolib.symmetric.mac.configuration.ConfigMacAlgorithmAndProvider;

public class DigitalEnvelopePolicyFromPropertiesTest {

    private static final String INVALID_PATH = "Invalid path";

    private static DigitalEnvelopePolicyFromProperties _digitalEnvelopePolicyFromProperties;

    @BeforeClass
    public static void setUp() throws GeneralCryptoLibException {

        _digitalEnvelopePolicyFromProperties =
            new DigitalEnvelopePolicyFromProperties(
                Constants.CRYPTOLIB_POLICY_PROPERTIES_FILE_PATH);
    }

    @Test
    public void testDigitalEnvelopeGetsSecureRandomAlgorithmAndProviderFromPolicy() {

        Assert.assertEquals(_digitalEnvelopePolicyFromProperties
            .getSecureRandomAlgorithmAndProvider().getAlgorithm(),
            getConfigSecureRandomAlgorithmAndProvider().getAlgorithm());

        Assert.assertEquals(_digitalEnvelopePolicyFromProperties
            .getSecureRandomAlgorithmAndProvider().getProvider(),
            getConfigSecureRandomAlgorithmAndProvider().getProvider());
    }

    @Test
    public void testDigitalEnvelopeGetsSecretKeyAlgorithmAndSpecFromPolicy() {

        Assert.assertEquals(_digitalEnvelopePolicyFromProperties
            .getSecretKeyAlgorithmAndSpec().getAlgorithm(),
            ConfigSecretKeyAlgorithmAndSpec.AES_128_SUNJCE.getAlgorithm());

        Assert.assertEquals(_digitalEnvelopePolicyFromProperties
            .getSecretKeyAlgorithmAndSpec().getProvider(),
            ConfigSecretKeyAlgorithmAndSpec.AES_128_SUNJCE.getProvider());

        Assert.assertEquals(_digitalEnvelopePolicyFromProperties
            .getSecretKeyAlgorithmAndSpec().getKeyLength(),
            ConfigSecretKeyAlgorithmAndSpec.AES_128_SUNJCE.getKeyLength());
    }

    @Test
    public void testDigitalEnvelopeGetsHmacSecretKeyAlgorithmAndSpecFromPolicy() {

        Assert.assertEquals(_digitalEnvelopePolicyFromProperties
            .getHmacSecretKeyAlgorithmAndSpec().getAlgorithm(),
            ConfigHmacSecretKeyAlgorithmAndSpec.HMACwithSHA256_256
                .getAlgorithm());

        Assert.assertEquals(_digitalEnvelopePolicyFromProperties
            .getHmacSecretKeyAlgorithmAndSpec().getKeyLengthInBits(),
            ConfigHmacSecretKeyAlgorithmAndSpec.HMACwithSHA256_256
                .getKeyLengthInBits());
    }

    @Test
    public void testDigitalEnvelopeGetsMacAlgorithmAndProviderFromPolicy() {

        Assert.assertEquals(_digitalEnvelopePolicyFromProperties
            .getMacAlgorithmAndProvider().getAlgorithm(),
            ConfigMacAlgorithmAndProvider.HMACwithSHA256_SUN
                .getAlgorithm());

        Assert
            .assertEquals(_digitalEnvelopePolicyFromProperties
                .getMacAlgorithmAndProvider().getProvider(),
                ConfigMacAlgorithmAndProvider.HMACwithSHA256_SUN
                    .getProvider());
    }

    @Test
    public void testDigitalEnvelopeGetsSymmetricCipherAlgorithmAndSpecFromPolicy() {

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getSymmetricCipherAlgorithmAndSpec()
                    .getAlgorithmAndModeAndPadding(),
                ConfigSymmetricCipherAlgorithmAndSpec.AESwithGCMandNOPADDING_96_128_BC
                    .getAlgorithmAndModeAndPadding());

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getSymmetricCipherAlgorithmAndSpec().getProvider(),
                ConfigSymmetricCipherAlgorithmAndSpec.AESwithGCMandNOPADDING_96_128_BC
                    .getProvider());

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getSymmetricCipherAlgorithmAndSpec()
                    .getInitVectorBitLength(),
                ConfigSymmetricCipherAlgorithmAndSpec.AESwithGCMandNOPADDING_96_128_BC
                    .getInitVectorBitLength());

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getSymmetricCipherAlgorithmAndSpec()
                    .getAuthTagBitLength(),
                ConfigSymmetricCipherAlgorithmAndSpec.AESwithGCMandNOPADDING_96_128_BC
                    .getAuthTagBitLength());
    }

    @Test
    public void testDigitalEnvelopeGetsAsymmetricCipherAlgorithmAndSpecFromPolicy() {

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getAsymmetricCipherAlgorithmAndSpec()
                    .getAlgorithmModePadding(),
                ConfigAsymmetricCipherAlgorithmAndSpec.RSAwithRSAKEMANDKDF1ANDSHA256_BC
                    .getAlgorithmModePadding());

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getAsymmetricCipherAlgorithmAndSpec().getProvider(),
                ConfigAsymmetricCipherAlgorithmAndSpec.RSAwithRSAKEMANDKDF1ANDSHA256_BC
                    .getProvider());
    }

    @Test
    public void testDigitalEnvelopeGetsEncryptionKeyPairAlgorithmAndSpecFromPolicy() {

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getEncryptingKeyPairAlgorithmAndSpec().getAlgorithm(),
                ConfigEncryptionKeyPairAlgorithmAndSpec.RSA_2048_F4_SUN_RSA_SIGN
                    .getAlgorithm());

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getEncryptingKeyPairAlgorithmAndSpec().getProvider(),
                ConfigEncryptionKeyPairAlgorithmAndSpec.RSA_2048_F4_SUN_RSA_SIGN
                    .getProvider());
    }

    @Test
    public void testDigitalEnvelopeGetsSigningKeyPairAlgorithmAndSpecFromPolicyr() {

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getSigningKeyPairAlgorithmAndSpec().getAlgorithm(),
                ConfigEncryptionKeyPairAlgorithmAndSpec.RSA_2048_F4_SUN_RSA_SIGN
                    .getAlgorithm());

        Assert
            .assertEquals(
                _digitalEnvelopePolicyFromProperties
                    .getSigningKeyPairAlgorithmAndSpec().getProvider(),
                ConfigEncryptionKeyPairAlgorithmAndSpec.RSA_2048_F4_SUN_RSA_SIGN
                    .getProvider());
    }

    @Test(expected = CryptoLibException.class)
    public void whenCreatePolicyFromInvalidPropertiesPathThenExceptionThrown()
            throws GeneralCryptoLibException {

        new DigitalEnvelopePolicyFromProperties(INVALID_PATH);
    }

    @Test(expected = CryptoLibException.class)
    public void whenCreatePolicyFromInvalidPropertyValuesThenExceptionThrown()
            throws GeneralCryptoLibException {

        new DigitalEnvelopePolicyFromProperties(
            "properties/cryptolibPolicy_invalidLabels.properties");
    }

    @Test(expected = CryptoLibException.class)
    public void whenCreatePolicyFromBlankPropertyValuesThenExceptionThrown()
            throws GeneralCryptoLibException {

        new DigitalEnvelopePolicyFromProperties(
            "properties/cryptolibPolicy_blankLabels.properties");
    }

    private static ConfigSecureRandomAlgorithmAndProvider getConfigSecureRandomAlgorithmAndProvider() {

        switch (OperatingSystem.current()) {

        case WINDOWS:
            return ConfigSecureRandomAlgorithmAndProvider.PRNG_SUN_MSCAPI;
        case LINUX:
            return ConfigSecureRandomAlgorithmAndProvider.NATIVE_PRNG_SUN;
        default:
            throw new CryptoLibException("OS not supported");
        }
    }
}
