/*
 * 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.products.ov.utils;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.Security;

import org.apache.commons.io.IOUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.service.AsymmetricService;
import com.scytl.cryptolib.primitives.primes.utils.PemUtils;

public class PasswordEncrypterTest {

    private static String RSA_PUBLIC_KEY_PATH = "/pem/rsaPublicKeyOfKeypair.pem";

    private static String RSA_PRIVATE_KEY_PATH = "/pem/rsaPrivateKeyOfKeypair.pem";

    private static final Charset CHAR_SET = StandardCharsets.UTF_8;

    private static AsymmetricService _asymmetricService;

    private static char[] _plaintextPassword = "Q5H4B5WUIQWCR6J3UQS2KEVVZU".toCharArray();

    private static PasswordEncrypter _target = new PasswordEncrypter(_asymmetricService);

    @BeforeClass
    public static void init() throws GeneralCryptoLibException {
        Security.addProvider(new BouncyCastleProvider());
        _asymmetricService = new AsymmetricService();
    }

    @Test
    public void givenEmptyPrivateKeyWhenEncryptThenReturnOriginalPassword()
            throws IOException, GeneralCryptoLibException {

        String NO_KEY = "";

        String encryptedPassword = _target.encryptPasswordIfEncryptionKeyAvailable(_plaintextPassword, NO_KEY);

        String errorMsg = "Encrypted password did not match original password";
        assertEquals(errorMsg, new String(_plaintextPassword), encryptedPassword);
    }

    @Test
    @Ignore
    public void whenEncryptAndDecryptUsingPrivateKeyPemThenOk() throws IOException, GeneralCryptoLibException {

        String publickey = readKeyAsString(RSA_PUBLIC_KEY_PATH);
        String privatekey = readKeyAsString(RSA_PRIVATE_KEY_PATH);

        String encryptedPassword = _target.encryptPasswordIfEncryptionKeyAvailable(_plaintextPassword, publickey);

        char[] decryptedPassword = _target.decryptPassword(encryptedPassword, privatekey);

        String errorMsg = "Decrypted password did not match original password";
        assertArrayEquals(errorMsg, _plaintextPassword, decryptedPassword);
    }

    @Test
    @Ignore
    public void whenEncryptAndDecryptUsingPrivateKeyThenOk() throws IOException, GeneralCryptoLibException {

        String publickeyAsPem = readKeyAsString(RSA_PUBLIC_KEY_PATH);
        String privatekeyAsPem = readKeyAsString(RSA_PRIVATE_KEY_PATH);
        PrivateKey privateKey = PemUtils.privateKeyFromPem(privatekeyAsPem);

        String encryptedPassword = _target.encryptPasswordIfEncryptionKeyAvailable(_plaintextPassword, publickeyAsPem);

        char[] decryptedPassword = _target.decryptPassword(encryptedPassword, privateKey);

        String errorMsg = "Decrypted password did not match original password";
        assertArrayEquals(errorMsg, _plaintextPassword, decryptedPassword);
    }

    private String readKeyAsString(final String path) throws IOException, GeneralCryptoLibException {

        InputStream inStream = getClass().getResourceAsStream(path);

        return IOUtils.toString(inStream, CHAR_SET);
    }
}
