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

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
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.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.utils.AsymmetricTestDataGenerator;
import com.scytl.cryptolib.certificates.bean.CertificateData;
import com.scytl.cryptolib.certificates.bean.RootCertificateData;
import com.scytl.cryptolib.certificates.bean.X509CertificateType;
import com.scytl.cryptolib.certificates.cryptoapi.CryptoAPIX509Certificate;
import com.scytl.cryptolib.certificates.factory.CryptoX509Certificate;
import com.scytl.cryptolib.certificates.utils.X509CertificateTestDataChecker;
import com.scytl.cryptolib.certificates.utils.X509CertificateTestDataGenerator;

/**
 * Tests of the certificates service API.
 */
public class CertificatesServiceTest {

    private static CertificatesService _certificatesServiceForDefaultPolicy;

    private static KeyPair _rootKeyPair;

    private static PublicKey _rootPublicKey;

    private static PrivateKey _rootPrivateKey;

    private static CertificateData _certificateData;

    @BeforeClass
    public static void setUp() throws Exception {

        Security.addProvider(new BouncyCastleProvider());

        _certificatesServiceForDefaultPolicy = new CertificatesService();

        _rootKeyPair = AsymmetricTestDataGenerator.getKeyPairForSigning();
        _rootPublicKey = _rootKeyPair.getPublic();
        _rootPrivateKey = _rootKeyPair.getPrivate();

        _certificateData =
            X509CertificateTestDataGenerator
                .getCertificateData(AsymmetricTestDataGenerator
                    .getKeyPairForSigning());
    }

    @AfterClass
    public static void tearDown() {

        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
    }

    @Test
    public final void testWhenCreateRootAuthorityCertificateFromServiceThenOk()
            throws GeneralCryptoLibException {

        RootCertificateData rootCertificateData =
            X509CertificateTestDataGenerator
                .getRootCertificateData(_rootKeyPair);

        CryptoAPIX509Certificate rootCertificate =
            _certificatesServiceForDefaultPolicy
                .createRootAuthorityX509Certificate(rootCertificateData,
                    _rootPrivateKey);

        X509CertificateTestDataChecker.assertCertificateContentCorrect(
            rootCertificate, rootCertificateData,
            X509CertificateType.CERTIFICATE_AUTHORITY, _rootPublicKey);
    }

    @Test
    public final void testWhenCreateIntermediateAuthorityCertificateFromServiceThenOk()
            throws GeneralCryptoLibException {

        CryptoAPIX509Certificate intermediateCertificate =
            _certificatesServiceForDefaultPolicy
                .createIntermediateAuthorityX509Certificate(
                    _certificateData, _rootPrivateKey);

        X509CertificateTestDataChecker.assertCertificateContentCorrect(
            intermediateCertificate, _certificateData,
            X509CertificateType.CERTIFICATE_AUTHORITY, _rootPublicKey);
    }

    @Test
    public final void testWhenCreateSignCertificateFromServiceThenOk()
            throws GeneralCryptoLibException {

        CryptoAPIX509Certificate signCertificate =
            _certificatesServiceForDefaultPolicy
                .createSignX509Certificate(_certificateData,
                    _rootPrivateKey);

        X509CertificateTestDataChecker.assertCertificateContentCorrect(
            signCertificate, _certificateData, X509CertificateType.SIGN,
            _rootPublicKey);
    }

    @Test
    public final void testWhenCreateEncryptionCertificateFromServiceThenOk()
            throws GeneralCryptoLibException {

        CryptoAPIX509Certificate encryptionCertificate =
            _certificatesServiceForDefaultPolicy
                .createEncryptionX509Certificate(_certificateData,
                    _rootPrivateKey);

        X509CertificateTestDataChecker.assertCertificateContentCorrect(
            encryptionCertificate, _certificateData,
            X509CertificateType.ENCRYPT, _rootPublicKey);
    }

    @Test
    public final void testWhenCreateRootAuthorityCertificateFromX509CertificateThenOk()
            throws GeneralCryptoLibException {

        CryptoAPIX509Certificate rootCertificate =
            _certificatesServiceForDefaultPolicy
                .createIntermediateAuthorityX509Certificate(
                    _certificateData, _rootPrivateKey);

        CryptoX509Certificate newRootCertificate =
            new CryptoX509Certificate(rootCertificate.getCertificate());

        X509CertificateTestDataChecker.assertCertificateContentCorrect(
            newRootCertificate, _certificateData,
            X509CertificateType.CERTIFICATE_AUTHORITY, _rootPublicKey);
    }

    @Test
    public final void testWhenCreateIntermediateAuthorityCertificateFromX509CertificateThenOk()
            throws GeneralCryptoLibException {

        CryptoAPIX509Certificate intermediateCertificate =
            _certificatesServiceForDefaultPolicy
                .createIntermediateAuthorityX509Certificate(
                    _certificateData, _rootPrivateKey);

        CryptoX509Certificate newIntermediateCertificate =
            new CryptoX509Certificate(
                intermediateCertificate.getCertificate());

        X509CertificateTestDataChecker.assertCertificateContentCorrect(
            newIntermediateCertificate, _certificateData,
            X509CertificateType.CERTIFICATE_AUTHORITY, _rootPublicKey);
    }

    @Test
    public final void testWhenCreateSignCertificateFromX509CertificateThenOk()
            throws GeneralCryptoLibException {

        CryptoAPIX509Certificate signCertificate =
            _certificatesServiceForDefaultPolicy
                .createSignX509Certificate(_certificateData,
                    _rootPrivateKey);

        CryptoX509Certificate newSignCertificate =
            new CryptoX509Certificate(signCertificate.getCertificate());

        X509CertificateTestDataChecker.assertCertificateContentCorrect(
            newSignCertificate, _certificateData,
            X509CertificateType.SIGN, _rootPublicKey);
    }

    @Test
    public final void testWhenCreateEncryptionCertificateFromX509CertificateThenOk()
            throws GeneralCryptoLibException {

        CryptoAPIX509Certificate encryptionCertificate =
            _certificatesServiceForDefaultPolicy
                .createEncryptionX509Certificate(_certificateData,
                    _rootPrivateKey);

        CryptoX509Certificate newEncryptionCertificate =
            new CryptoX509Certificate(
                encryptionCertificate.getCertificate());

        X509CertificateTestDataChecker.assertCertificateContentCorrect(
            newEncryptionCertificate, _certificateData,
            X509CertificateType.ENCRYPT, _rootPublicKey);
    }
}
