/*
 * 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.commons.cms;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.UnrecoverableEntryException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.cms.CMSAttributeTableGenerator;
import org.bouncycastle.cms.SignerInfoGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.products.ov.commons.signature.SignatureFactory;

/**
 * Tests of {@link SignerInfoGeneratorBuilder}.
 */
public class SignerInfoGeneratorBuilderTest {
    private static final char[] PASSWORD =
        "6JUZUTMZVEWGZVKM".toCharArray();

    private static final String ALIAS = "signing";

    private static final AlgorithmIdentifier IDENTIFIER =
        new AlgorithmIdentifier(
            PKCSObjectIdentifiers.sha256WithRSAEncryption,
            DERNull.INSTANCE);

    private ContentSignerFactory signerFactory;

    private PrivateKeyEntry entry;

    private CMSAttributeTableGenerator signedAttributeGenerator;

    private CMSAttributeTableGenerator unsignedAttributeGenerator;
    
    private static KeyStore store = null;
    
    @BeforeClass
    public static void init() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, GeneralCryptoLibException {
        Security.addProvider(new BouncyCastleProvider());
        store = CertificateUtil.createTestP12("testForSignerInfoGeneratorBuilder.p12", PASSWORD, ALIAS);
    }
    @Before
    public void setUp()
            throws NoSuchAlgorithmException, KeyStoreException,
            IOException, CertificateException,
            UnrecoverableEntryException {
        SignatureFactory signatureFactory = mock(SignatureFactory.class);
        when(signatureFactory.newSignature())
            .thenReturn(Signature.getInstance("SHA256withRSA"));
        SecureRandom secureRandom = new SecureRandom();
        signerFactory =
            new ContentSignerFactoryImpl(signatureFactory, IDENTIFIER, secureRandom);
        entry = (PrivateKeyEntry) store.getEntry(ALIAS,
            new PasswordProtection(PASSWORD));
        signedAttributeGenerator = mock(CMSAttributeTableGenerator.class);
        unsignedAttributeGenerator =
            mock(CMSAttributeTableGenerator.class);
    }

    @Test
    public void testBuild()
            throws IOException, InvalidKeyException,
            GeneralSecurityException {
        SignerInfoGenerator generator =
            new SignerInfoGeneratorBuilder(signerFactory)
                .setPrivateKey(entry.getPrivateKey())
                .setCertificate((X509Certificate) entry.getCertificate())
                .setDirectSignature(false)
                .setSignedAttributeGenerator(signedAttributeGenerator)
                .setUnsignedAttributeGenerator(unsignedAttributeGenerator)
                .build();
        assertEquals(signedAttributeGenerator,
            generator.getSignedAttributeTableGenerator());
        assertEquals(unsignedAttributeGenerator,
            generator.getUnsignedAttributeTableGenerator());
        assertArrayEquals(entry.getCertificate().getEncoded(),
            generator.getAssociatedCertificate().getEncoded());
    }

    @Test
    public void testBuildDirectSignature()
            throws IOException, InvalidKeyException,
            GeneralSecurityException {
        SignerInfoGenerator generator =
            new SignerInfoGeneratorBuilder(signerFactory)
                .setPrivateKey(entry.getPrivateKey())
                .setCertificate((X509Certificate) entry.getCertificate())
                .setDirectSignature(true)
                .setSignedAttributeGenerator(signedAttributeGenerator)
                .setUnsignedAttributeGenerator(unsignedAttributeGenerator)
                .build();
        assertNull(generator.getSignedAttributeTableGenerator());
        assertNull(generator.getUnsignedAttributeTableGenerator());
        assertArrayEquals(entry.getCertificate().getEncoded(),
            generator.getAssociatedCertificate().getEncoded());
    }
}
