public static synchronized X509Certificate createX509V3Certificate(KeyPair kp, int days, String issuerCommonName,
                                                                        String subjectCommonName, String domain,
                                                                        String signAlgoritm)
            throws GeneralSecurityException, IOException {
        return createX509V3Certificate( kp, days, issuerCommonName, subjectCommonName, domain, signAlgoritm, null );
    }
@Test
    public void testGenerateCertificateDateValidity() throws Exception
    {
        // Setup fixture.
        final KeyPair keyPair = subjectKeyPair;
        final int days = 2;
        final String issuerCommonName = "issuer common name";
        final String subjectCommonName = "subject common name";
        final String domain = "domain.example.org";
        final Set<String> sanDnsNames = Stream.of( "alternative-a.example.org", "alternative-b.example.org" ).collect( Collectors.toSet() );

        // Execute system under test.
        final X509Certificate result = CertificateManager.createX509V3Certificate( keyPair, days, issuerCommonName, subjectCommonName, domain, SIGNATURE_ALGORITHM, sanDnsNames );

        // Verify results.
        assertNotNull( result );

        assertCertificateDateValid( "The generated certificate is expected to be valid immediately (but is not).", result, new Date() );
        assertCertificateDateValid( "The generated certificate is expected to be valid half was during its maximum validity period (but is not).", result, addDays( days / 2 ) );
        assertCertificateDateNotValid( "The generated certificate is not expected to be valid on a date before it was created (but is).", result, addDays( -1 ) );
        assertCertificateDateNotValid( "The generated certificate is not expected to be valid after its maximum validity period has ended (but is).", result, addDays( days * 2 ) );
    }