/*
 * 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.symmetric.service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.Security;

import javax.crypto.SecretKey;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.derivation.cryptoapi.CryptoAPIDerivedKey;
import com.scytl.cryptolib.derivation.cryptoapi.CryptoAPIKDFDeriver;
import com.scytl.cryptolib.derivation.cryptoapi.CryptoAPIPBKDFDeriver;
import com.scytl.cryptolib.primitives.service.PrimitivesService;

import mockit.Tested;

public class SymmetricServiceIT {

    @Tested
    private SymmetricService _target;

    private PrimitivesService _primitivesService;

    @Before
    public void setup() throws GeneralCryptoLibException {
        Security.addProvider(new BouncyCastleProvider());
        _primitivesService = new PrimitivesService();
    }

    @After
    public void tearDown() {
        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
    }

    @Test
    public void generateKey()
            throws GeneralSecurityException, IOException,
            GeneralCryptoLibException {
        SymmetricService symmetricService = new SymmetricService();

        SecretKey secretKeyForEncryption =
            symmetricService.getSecretKeyForEncryption();
        saveSecretKey(secretKeyForEncryption);
    }

    private void saveSecretKey(final SecretKey secretKeyForEncryption)
            throws GeneralSecurityException, IOException {
        try (OutputStream out = new ByteArrayOutputStream()) {
            out.write(secretKeyForEncryption.getEncoded());
        }
    }

    @Test
    public void getSecretKeyForEncryptionFromKDFKeyTest()
            throws GeneralCryptoLibException {

        CryptoAPIKDFDeriver kdfDeriver = _primitivesService.getKDFDeriver();
        CryptoAPIDerivedKey key = kdfDeriver.deriveKey("mySeed".getBytes(), 32);

        SecretKey secretKey =
            _target.getSecretKeyForEncryptionFromDerivedKey(key);
        _target.encrypt(secretKey, "myData".getBytes());
    }

    @Test
    public void getSecretKeyForMacFromKDFKeyTest()
            throws GeneralCryptoLibException {

        CryptoAPIKDFDeriver kdfDeriver = _primitivesService.getKDFDeriver();
        CryptoAPIDerivedKey key = kdfDeriver.deriveKey("mySeed".getBytes(), 32);

        SecretKey secretKey = _target.getSecretKeyForMacFromDerivedKey(key);
        _target.getMac(secretKey, "myData".getBytes());
    }

    @Test
    public void getSecretKeyForEncriptionFromPBKDFKeyTest()
            throws GeneralCryptoLibException {

        CryptoAPIPBKDFDeriver pbkdfDeriver =
            _primitivesService.getPBKDFDeriver();
        CryptoAPIDerivedKey key =
            pbkdfDeriver.deriveKey("password01234567890".toCharArray(),
                "saltsaltsaltsaltsaltsaltsaltsalt".getBytes());

        SecretKey secretKey =
            _target.getSecretKeyForEncryptionFromDerivedKey(key);
        _target.encrypt(secretKey, "myData".getBytes());
    }

    @Test
    public void getSecretKeyForMacFromPBKDFKeyTest()
            throws GeneralCryptoLibException {

        CryptoAPIPBKDFDeriver pbkdfDeriver =
            _primitivesService.getPBKDFDeriver();
        CryptoAPIDerivedKey key =
            pbkdfDeriver.deriveKey("password01234567890".toCharArray(),
                "saltsaltsaltsaltsaltsaltsaltsalt".getBytes());

        SecretKey secretKey = _target.getSecretKeyForMacFromDerivedKey(key);
        _target.getMac(secretKey, "myData".getBytes());
    }

    @Test
    public void getSecretKeyForEncryptionFromDerivedPasswordTest()
            throws GeneralCryptoLibException {
        CryptoAPIPBKDFDeriver deriver = _primitivesService.getPBKDFDeriver();
        CryptoAPIDerivedKey key =
            deriver.deriveKey("password01234567890".toCharArray(),
                "saltsaltsaltsaltsaltsaltsaltsalt".getBytes());

        SecretKey secretKey =
            _target.getSecretKeyForEncryptionFromDerivedKey(key);
        byte[] encrypt = _target.encrypt(secretKey, "myData".getBytes());
    }
}
