/*
 * 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.cipher.factory;

import static mockit.Deencapsulation.getField;
import static org.junit.Assert.assertEquals;

import java.security.Security;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.CryptoLibException;
import com.scytl.cryptolib.asymmetric.cipher.configuration.AsymmetricCipherPolicy;
import com.scytl.cryptolib.asymmetric.cipher.configuration.ConfigAsymmetricCipherAlgorithmAndSpec;
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.ConfigSecretKeyAlgorithmAndSpec;

public class AsymmetricCipherFactoryTest {

    @BeforeClass
    public static void setUp() {
        Security.addProvider(new BouncyCastleProvider());
    }

    @AfterClass
    public static void removeBouncyCastleProvider() {
        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
    }

    @Test
    public void whenCreateAsymmetricCipherFactoryUsingPolicyRsaKemMgf1WithSha256AndNoPaddingAndBc() {

        AsymmetricCipherFactory asymmetricCipherFactoryByPolicy =
            new AsymmetricCipherFactory(
                getAsymmetricCipherPolicyRsaKemWithKdf2AndSha256AndBc());

        AsymmetricCipherPolicy expectedAsymmetricCipherPolicy =
            getField(asymmetricCipherFactoryByPolicy,
                "_asymmetricCipherPolicy");

        assertEquals(
            getAsymmetricCipherPolicyRsaKemWithKdf2AndSha256AndBc()
                .getAsymmetricCipherAlgorithmAndSpec(),
            expectedAsymmetricCipherPolicy
                .getAsymmetricCipherAlgorithmAndSpec());
    }

    private AsymmetricCipherPolicy getAsymmetricCipherPolicyRsaKemWithKdf2AndSha256AndBc() {
        return new AsymmetricCipherPolicy() {

            @Override
            public ConfigAsymmetricCipherAlgorithmAndSpec getAsymmetricCipherAlgorithmAndSpec() {
                return ConfigAsymmetricCipherAlgorithmAndSpec.RSAwithRSAKEMANDKDF2ANDSHA256_BC;
            }

            @Override
            public ConfigSecureRandomAlgorithmAndProvider getSecureRandomAlgorithmAndProvider() {
                return getSecureRandomConfig();
            }

            @Override
            public ConfigSecretKeyAlgorithmAndSpec getSecretKeyAlgorithmAndSpec() {
                return ConfigSecretKeyAlgorithmAndSpec.AES_128_SUNJCE;
            }

            @Override
            public ConfigSymmetricCipherAlgorithmAndSpec getSymmetricCipherAlgorithmAndSpec() {
                return ConfigSymmetricCipherAlgorithmAndSpec.AESwithGCMandNOPADDING_96_128_BC;
            }
        };
    }

    private static ConfigSecureRandomAlgorithmAndProvider getSecureRandomConfig() {

        switch (OperatingSystem.current()) {

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