/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wildfly.security.x500.cert;
import static org.junit.Assert.*;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.security.auth.x500.X500Principal;
import org.junit.Test;
import org.wildfly.security.asn1.ASN1Encodable;
import org.wildfly.security.x500.GeneralName;
import org.wildfly.security.x500.X500;
import org.wildfly.security.x500.X500AttributeTypeAndValue;
import org.wildfly.security.x500.X500PrincipalBuilder;
/**
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
*/
public class X509CertificateBuilderTest {
static final PrivateKey signingKey;
static final PublicKey publicKey;
static final PublicKey signingPublicKey;
static {
KeyPairGenerator keyPairGenerator;
try {
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new Error(e);
}
final KeyPair keyPair1 = keyPairGenerator.generateKeyPair();
final KeyPair keyPair2 = keyPairGenerator.generateKeyPair();
signingKey = keyPair1.getPrivate();
signingPublicKey = keyPair1.getPublic();
publicKey = keyPair2.getPublic();
}
private static X509CertificateBuilder populateBasicCertBuilder() throws NoSuchAlgorithmException {
X509CertificateBuilder builder = new X509CertificateBuilder();
X500PrincipalBuilder principalBuilder = new X500PrincipalBuilder();
principalBuilder.addItem(X500AttributeTypeAndValue.create(X500.OID_AT_COMMON_NAME, ASN1Encodable.ofUtf8String("jane")));
final X500Principal dn = principalBuilder.build();
builder.setIssuerDn(dn);
builder.setSubjectDn(dn);
builder.setSignatureAlgorithmName("SHA256withRSA");
builder.setSigningKey(signingKey);
builder.setPublicKey(publicKey);
return builder;
}
@Test
public void testBasic() throws Exception {
X509CertificateBuilder builder = populateBasicCertBuilder();
final X509Certificate certificate = builder.build();
// basically check every field here
assertTrue(Arrays.equals(certificate.getTBSCertificate(), builder.getTBSBytes()));
// just to be sure!
assertEquals("CN=jane", certificate.getIssuerX500Principal().getName());
assertEquals("CN=jane", certificate.getSubjectX500Principal().getName());
// if the TBS certs are equals, this should always work
certificate.verify(signingPublicKey, KeyFactory.getInstance("RSA").getProvider());
}
@Test
public void testAKIExtension() throws Exception {
X509CertificateBuilder builder = populateBasicCertBuilder();
builder.addExtension(new AuthorityKeyIdentifierExtension(new byte[] { 1, 2, 3, 4 }, Collections.singletonList(new GeneralName.DNSName("foo.com")), BigInteger.TEN));
assertTrue(Arrays.equals(builder.build().getTBSCertificate(), builder.getTBSBytes()));
builder = populateBasicCertBuilder();
builder.addExtension(new AuthorityKeyIdentifierExtension(null, Collections.singletonList(new GeneralName.DNSName("foo.com")), BigInteger.TEN));
assertTrue(Arrays.equals(builder.build().getTBSCertificate(), builder.getTBSBytes()));
builder = populateBasicCertBuilder();
builder.addExtension(new AuthorityKeyIdentifierExtension(new byte[] { 1, 2, 3, 4 }, null, BigInteger.TEN));
assertTrue(Arrays.equals(builder.build().getTBSCertificate(), builder.getTBSBytes()));
builder = populateBasicCertBuilder();
builder.addExtension(new AuthorityKeyIdentifierExtension(new byte[] { 1, 2, 3, 4 }, Collections.singletonList(new GeneralName.DNSName("foo.com")), null));
assertTrue(Arrays.equals(builder.build().getTBSCertificate(), builder.getTBSBytes()));
}
@Test
public void testIssuerAltNamesExtension() throws Exception {
X509CertificateBuilder builder = populateBasicCertBuilder();
builder.addExtension(new IssuerAlternativeNamesExtension(true, Arrays.asList(new GeneralName.RFC822Name("elytron@wildfly.org"), new GeneralName.DNSName("elytron.wildfly.org"))));
final X509Certificate certificate = builder.build();
assertTrue(Arrays.equals(certificate.getTBSCertificate(), builder.getTBSBytes()));
final Collection<List<?>> names = certificate.getIssuerAlternativeNames();
assertEquals(2, names.size());
final Iterator<List<?>> iterator = names.iterator();
List<?> item = iterator.next();
assertEquals(2, item.size());
assertEquals(Integer.valueOf(GeneralName.RFC_822_NAME), item.get(0));
assertEquals("elytron@wildfly.org", item.get(1));
item = iterator.next();
assertEquals(2, item.size());
assertEquals(Integer.valueOf(GeneralName.DNS_NAME), item.get(0));
assertEquals("elytron.wildfly.org", item.get(1));
}
@Test
public void testSubjectAltNamesExtension() throws Exception {
X509CertificateBuilder builder = populateBasicCertBuilder();
builder.addExtension(new SubjectAlternativeNamesExtension(true, Arrays.asList(new GeneralName.RFC822Name("elytron@wildfly.org"), new GeneralName.DNSName("elytron.wildfly.org"))));
final X509Certificate certificate = builder.build();
assertTrue(Arrays.equals(certificate.getTBSCertificate(), builder.getTBSBytes()));
final Collection<List<?>> names = certificate.getSubjectAlternativeNames();
assertEquals(2, names.size());
final Iterator<List<?>> iterator = names.iterator();
List<?> item = iterator.next();
assertEquals(2, item.size());
assertEquals(Integer.valueOf(GeneralName.RFC_822_NAME), item.get(0));
assertEquals("elytron@wildfly.org", item.get(1));
item = iterator.next();
assertEquals(2, item.size());
assertEquals(Integer.valueOf(GeneralName.DNS_NAME), item.get(0));
assertEquals("elytron.wildfly.org", item.get(1));
}
@Test
public void testEKUExtension() throws Exception {
X509CertificateBuilder builder = populateBasicCertBuilder();
final List<String> usage = Arrays.asList(X500.OID_KP_CLIENT_AUTH, X500.OID_KP_SERVER_AUTH);
builder.addExtension(new ExtendedKeyUsageExtension(true, usage));
final X509Certificate certificate = builder.build();
assertTrue(Arrays.equals(certificate.getTBSCertificate(), builder.getTBSBytes()));
assertEquals(usage, certificate.getExtendedKeyUsage());
}
@Test
public void testKUExtension() throws Exception {
X509CertificateBuilder builder = populateBasicCertBuilder();
builder.addExtension(new KeyUsageExtension(KeyUsage.digitalSignature, KeyUsage.keyAgreement, KeyUsage.keyEncipherment, KeyUsage.decipherOnly));
final X509Certificate certificate = builder.build();
assertTrue(Arrays.equals(certificate.getTBSCertificate(), builder.getTBSBytes()));
final boolean[] keyUsage = certificate.getKeyUsage();
assertNotNull(keyUsage);
assertTrue(KeyUsage.digitalSignature.in(keyUsage));
assertFalse(KeyUsage.nonRepudiation.in(keyUsage));
assertTrue(KeyUsage.keyEncipherment.in(keyUsage));
assertFalse(KeyUsage.dataEncipherment.in(keyUsage));
assertTrue(KeyUsage.keyAgreement.in(keyUsage));
assertFalse(KeyUsage.keyCertSign.in(keyUsage));
assertFalse(KeyUsage.cRLSign.in(keyUsage));
assertFalse(KeyUsage.encipherOnly.in(keyUsage));
assertTrue(KeyUsage.decipherOnly.in(keyUsage));
}
}