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

import java.security.PublicKey;
import java.util.Date;

import org.junit.Assert;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.certificates.bean.RootCertificateData;
import com.scytl.cryptolib.certificates.bean.X509CertificateType;
import com.scytl.cryptolib.certificates.constants.X509CertificateConstants;
import com.scytl.cryptolib.certificates.cryptoapi.CryptoAPIX509Certificate;

/**
 * Utility to check various types of certificate data generated by tests.
 */
public class X509CertificateTestDataChecker {

    /**
     * Asserts that a certificate contains the correct content. If any content
     * is incorrect, an error message specific to this content is output when
     * the assertion fails.
     * 
     * @param certificate
     *            the certificate to be checked.
     * @param certificateData
     *            the data used to generate the certificate.
     * @param certificateType
     *            the type of the certificate.
     * @param issuerPublicKey
     *            the public key of the certificate issuer.
     * @throws GeneralCryptoLibException
     *             if there is an error when accessing data from the
     *             certificate.
     */
    public static final void assertCertificateContentCorrect(
            final CryptoAPIX509Certificate certificate,
            final RootCertificateData certificateData,
            final X509CertificateType certificateType,
            final PublicKey issuerPublicKey)
            throws GeneralCryptoLibException {

        Assert
            .assertTrue(
                "Serial number bit length "
                    + certificate.getSerialNumber().bitLength()
                    + " exceeds maximum "
                    + X509CertificateConstants.CERTIFICATE_SERIAL_NUMBER_MAX_BIT_LENGTH,
                (certificate.getSerialNumber().bitLength() <= X509CertificateConstants.CERTIFICATE_SERIAL_NUMBER_MAX_BIT_LENGTH));

        Assert.assertTrue("Validity check failed.",
            certificate.checkValidity());

        Date validDate =
            X509CertificateTestDataGenerator.getDateWithinValidityPeriod();
        Assert.assertTrue("Validity check failed for date " + validDate,
            certificate.checkValidity(validDate));

        Assert.assertEquals("Unexpected issuer DN",
            certificateData.getIssuerDn(), certificate.getIssuerDn());

        Assert.assertEquals("Unexpected subject DN",
            certificateData.getSubjectDn(), certificate.getSubjectDn());

        Assert.assertEquals("Unexpected starting date of validity",
            X509CertificateTestDataGenerator
                .getEpochTimeString(certificateData.getValidityDates()
                    .getNotBefore()), X509CertificateTestDataGenerator
                .getEpochTimeString(certificate.getNotBefore()));

        Assert.assertEquals("Unexpected ending date of validity",
            X509CertificateTestDataGenerator
                .getEpochTimeString(certificateData.getValidityDates()
                    .getNotAfter()), X509CertificateTestDataGenerator
                .getEpochTimeString(certificate.getNotAfter()));

        Assert.assertArrayEquals("Unexpected public key ", certificateData
            .getSubjectPublicKey().getEncoded(), certificate
            .getPublicKey().getEncoded());

        Assert.assertTrue("Certificate is not expected type: "
            + certificateType,
            certificate.isCertificateType(certificateType));

        Assert.assertTrue(
            "Certificate signature verification by issuer failed.",
            certificate.verify(issuerPublicKey));
    }
}
