/*
 * 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.elgamal.encrytionparams;

import static org.junit.Assert.assertTrue;

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.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.commons.utils.system.OperatingSystem;
import com.scytl.cryptolib.elgamal.bean.ElGamalEncryptionParameters;
import com.scytl.cryptolib.elgamal.configuration.ConfigGroupType;
import com.scytl.cryptolib.elgamal.configuration.ElGamalPolicy;
import com.scytl.cryptolib.primitives.securerandom.configuration.ConfigSecureRandomAlgorithmAndProvider;
import com.scytl.cryptolib.primitives.securerandom.factory.CryptoRandomBytes;
import com.scytl.cryptolib.primitives.securerandom.factory.SecureRandomFactory;

public class ElGamalEncryptionParamsGeneratorTest {

    public static final int CERTAINTY_LEVEL = 80;

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

    @AfterClass
    public static void tearDown() {

        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
    }

    @Test
    public void testGenerate() throws GeneralCryptoLibException {

        int certainty = CERTAINTY_LEVEL;

        ElGamalPolicy policy = getPolicy();
        CryptoRandomBytes cryptoRandomBytes =
            new SecureRandomFactory(policy).createByteRandom();

        ElGamalEncryptionParameters params =
            new ElGamalEncryptionParamsGenerator(policy.getGroupType()
                .getL(), policy.getGroupType().getN(), certainty,
                cryptoRandomBytes).generate();

        assertTrue(params.getP().isProbablePrime(certainty));
        assertTrue(params.getQ().isProbablePrime(certainty));

        int constructedPLength = params.getP().bitLength();
        assertTrue(constructedPLength <= policy.getGroupType().getL());

        int constructedQLength = params.getQ().bitLength();
        assertTrue(constructedQLength <= policy.getGroupType().getN());
    }

    private static ElGamalPolicy getPolicy() {

        return new ElGamalPolicy() {

            @Override
            public ConfigGroupType getGroupType() {
                return ConfigGroupType.ZP_2048_256;
            }

            @Override
            public ConfigSecureRandomAlgorithmAndProvider getSecureRandomAlgorithmAndProvider() {

                switch (OperatingSystem.current()) {

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