@Test
void generateEndEntitySignedCertificateVersion3() throws Exception
{

    CertifiedPublicKey caCertificate =
        factory.getInstance(signerFactory.getInstance(true, rsaPrivateKey),
            new X509CertificateGenerationParameters(
                builder.addBasicConstraints(true)
                    .addKeyUsage(true, EnumSet.of(KeyUsage.keyCertSign,
                        KeyUsage.cRLSign))
                    .build()))
            .generate(new DistinguishedName("CN=Test CA"), rsaPublicKey,
                new X509CertificateParameters());
    builder = componentManager.getInstance(X509ExtensionBuilder.class);
    CertificateGenerator generator = factory.getInstance(
        CertifyingSigner.getInstance(true, new CertifiedKeyPair(rsaPrivateKey, caCertificate), signerFactory),
        new X509CertificateGenerationParameters(
            builder.addKeyUsage(EnumSet.of(KeyUsage.digitalSignature,
                KeyUsage.dataEncipherment))
                .addExtendedKeyUsage(false,
                    new ExtendedKeyUsages(new String[]{ ExtendedKeyUsages.EMAIL_PROTECTION }))
                .build()));
    builder = componentManager.getInstance(X509ExtensionBuilder.class);
    CertifiedPublicKey certificate =
        generator.generate(new DistinguishedName("CN=Test End Entity"), dsaPublicKey,
            new X509CertificateParameters(
                builder.addSubjectAltName(false,
                    new X509GeneralName[]{
                        new X509Rfc822Name("test@example.com"),
                        new X509Rfc822Name(new InternetAddress("test@test.com")),
                        new X509DnsName("example.com"),
                        new X509DirectoryName("CN=Test"),
                        new X509IpAddress("192.168.1.1"),
                        new X509IpAddress("192.168.2.0/24"),
                        new X509IpAddress("192.168.3.0/255.255.255.0"),
                        new X509IpAddress(InetAddress.getByName("192.168.4.1")),
                        new X509IpAddress(InetAddress.getByName("192.168.5.0"),
                            InetAddress.getByName("255.255.255.0")),
                        new X509IpAddress("2001:db8:0:85a3::ac1f:8001"),
                        new X509IpAddress("2001:db8:1f89::/48"),
                        new X509IpAddress(InetAddress.getByName("2001:db8:0:85a3::ac1f:8001")),
                        new X509IpAddress(InetAddress.getByName("2001:db8:1f89::"),
                            InetAddress.getByName("ffff:ffff:ffff::")),
                        new X509URI("http://xwiki.org"),
                        new X509URI(new URL("http://myxwiki.org"))
                    })
                    .build()
            ));
    X509CertifiedPublicKey cert = checkRootSigned(certificate, 3);
    assertThat(cert.getExtensions().getExtensionOID(),
        equalTo(new String[]{ "2.5.29.35", "2.5.29.14", "2.5.29.15", "2.5.29.37", "2.5.29.17" }));
    assertThat(cert.getExtensions().getCriticalExtensionOID(), equalTo(new String[]{ "2.5.29.15" }));
    assertThat(cert.getExtensions().getNonCriticalExtensionOID(),
        equalTo(new String[]{ "2.5.29.35", "2.5.29.14", "2.5.29.37", "2.5.29.17" }));
    assertTrue(cert.getExtensions().isCritical(KeyUsage.OID), "KeyUsage extension should be critical.");
    assertThat(cert.getExtensions().getKeyUsage(), equalTo(EnumSet.of(KeyUsage.digitalSignature,
        KeyUsage.dataEncipherment)));
    assertFalse(cert.getExtensions().isCritical(ExtendedKeyUsages.OID),
        "ExtendedKeyUsage extension should be non critical.");
    assertThat(cert.getExtensions().getExtendedKeyUsage().getAll().toArray(new String[0]), equalTo(
        new String[]{ ExtendedKeyUsages.EMAIL_PROTECTION }));
    assertTrue(cert.getExtensions().getExtendedKeyUsage().hasUsage(ExtendedKeyUsages.EMAIL_PROTECTION),
        "Email data protection extended usage should be set.");
    List<X509GeneralName> names = cert.getExtensions().getSubjectAltName();
    assertThat(names.size(), equalTo(15));
    for (X509GeneralName name : names) {
        if (name instanceof X509Rfc822Name) {
            assertThat(((X509StringGeneralName) name).getName(),
                anyOf(equalTo("test@example.com"), equalTo("test@test.com")));
            assertThat(((X509Rfc822Name) name).getAddress(), anyOf(equalTo(new InternetAddress("test@example.com")),
                equalTo(new InternetAddress("test@test.com"))));
        } else if (name instanceof X509DnsName) {
            assertThat(((X509StringGeneralName) name).getName(), equalTo("example.com"));
            assertThat(((X509DnsName) name).getDomain(), equalTo("example.com"));
        } else if (name instanceof X509DirectoryName) {
            assertThat(((X509StringGeneralName) name).getName(), equalTo("CN=Test"));
        } else if (name instanceof X509URI) {
            assertThat(((X509StringGeneralName) name).getName(), anyOf(equalTo("http://xwiki.org"),
                equalTo("http://myxwiki.org")));
            assertThat(((X509URI) name).getURI(), anyOf(equalTo(new URI("http://xwiki.org")),
                equalTo(new URI("http://myxwiki.org"))));
            assertThat(((X509URI) name).getURL(), anyOf(equalTo(new URL("http://xwiki.org")),
                equalTo(new URL("http://myxwiki.org"))));
        } else if (name instanceof X509IpAddress) {
            assertTrue(IPAddress.isValid(((X509StringGeneralName) name).getName())
                    || IPAddress.isValidWithNetMask(((X509StringGeneralName) name).getName()),
                "Invalid IP address: " + ((X509StringGeneralName) name).getName());
        } else {
            fail("Unexpected SubjectAltName type.");
        }
    }
}