/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.openstack.atlas.util.ca.util; import org.openstack.atlas.util.ca.util.X509ChainEntry; import org.openstack.atlas.util.ca.util.X509PathBuilder; import java.security.KeyPair; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.bouncycastle.jce.PKCS10CertificationRequest; import org.bouncycastle.jce.X509Principal; import org.bouncycastle.jce.provider.X509CertificateObject; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.openstack.atlas.util.ca.PemUtils; import org.openstack.atlas.util.ca.exceptions.NotAnRSAKeyException; import org.openstack.atlas.util.ca.exceptions.NotAnX509CertificateException; import static org.junit.Assert.*; import org.openstack.atlas.util.ca.CertUtils; import org.openstack.atlas.util.ca.exceptions.PemException; import org.openstack.atlas.util.ca.exceptions.RsaException; public class X509PathBuilderTest { private static final String rootKeyPem = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEowIBAAKCAQEAi2AMd8rFoe3Re9R0ipd2zARspYWqzOwnn2H7eqxGb08zFSQA\n" + "RQ/gUtl0MbNocwe063qEpEKJ646BKtaM/3BeH3o2ZBZoUKPl3kaietHuGM9DN9EC\n" + "gftl2CeCz8OXfR92vEUhZ/A+lep8NDqnFSXuUhgaZQOuIamrdKqjEB1THZoYNAby\n" + "fsdWC1JNv8s/S+IqoHCxuBaezq8CTGtNHjtwRhbSUYKzceu8Tk3ha+/d2YKubVM1\n" + "8mdswtNGdQau5kVIi847TaCiBBNGE24Iei9D668nsZaDw+NpvwlJw45cBwgMnYyn\n" + "aF6jtgs8tE09BrnTWcRU1DSTyHuecLS62cUwjwIDAQABAoIBAAqzjUGFaDdOs072\n" + "uRwLFSwFCvKKmNqzJzetpkl9AMt7IUj2Qq8K0QaLe8h1JgfvB40tExIpqb1Ua8aG\n" + "Qr06O3/fOl3k+o12iCfQ9JjJlaaCA389pRul2eQG5JxfQDpzOAKsrCv23ldUccTw\n" + "2/Nbvji/cQdgiPY8uNV0ZKDQH5meJeZHuzWIrGZ8dPgoFNs098Li+sEJ3llXCmBr\n" + "mMleOkT3EGdFh1KLQuyBld4IVyoQzq4kmD6QpocTM+ne9RBC60TrUhCdoIoaOXeH\n" + "T/ur83AqXMqDFxysmpyiud9cTSjE3L50XgeGtTQDFQEEOyGbO6XWAl25upvYU6cb\n" + "WlAdoEECgYEA3tBYTn2dfvum3b7B/FTt62a2OKmq4UNZvz/MpqsIlV6NKYTFVUHt\n" + "eexnUpSlKsEk4U23CzJwv5KcHy2F00s2DP04W8cEpR9OhBKRV2xQ0CsQ+CTTFsUh\n" + "TZf+khSTEzIpbQSJzKNvAtZjmrXEjmf64m79WO7+03V9yqvOe40zFlUCgYEAoCJG\n" + "x/WR7rWuHFXXWmcxJS9qAgJiAPE29IbSRvXk7xd+zevGzOLwjN/W+K3elNrpXNig\n" + "UakgVoMniRtm3UX/llM8Ysj3GJVDjwou7fOfAZWWm5AGf1JpA6tzZCSyM9EalAh4\n" + "p7JhWLJ2vd5Rhtg3JPVGXPoqVqD8OYv4fWSWJ1MCgYB9MQUc/Pl8OrtURnVKaRHR\n" + "PUHPbo2Dykrn6Vn8n4bQHnMkS+Rwdf2PjuOzA7AV6LXnHbpmQS4WhbLQ1cwmn1C8\n" + "VZ7P+m/Cs2dzT9d4DnUNsdT0CATO+24t4eP4gjTtCTc7eNxQLdgW+Qy4Bb9t4ECX\n" + "75LL4GUvvQkz0frPctOsjQKBgQCdx+gyEfcOW5kIdlRQ0SiNWSB8hliGUSYy3bzH\n" + "CnXeVyosP8qMCne2dr9cHAUaanBReWjNzXT9iREleQhrshLZzX3MX/OIF1qP0BrZ\n" + "fpgHeZsCAHFGdq7eXMq/u6CSidBEV+x6X7qnKIDzJ+Dwmo4LLll8N0oMPWcIVLAs\n" + "7TU93QKBgH0F0U5wj1xiI/uOBGQAAD14jUfPRKXNpcPv7Vr2CVrBjuwGai/HVauY\n" + "Boods91VGHE9T5t2COxBtUDfyNU+RCzLI59he693VzUgfaDL6pm7U8hFAok2rDuN\n" + "6Xoig390LnodozdBpfp5bl1psREQ9Gs5aZDvkonN8WsMSrnLZezf\n" + "-----END RSA PRIVATE KEY-----\n" + ""; private static final String rootCrtPem = "-----BEGIN CERTIFICATE-----\n" + "MIIDyTCCArGgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBjTEeMBwGA1UEAxMVVGVz\n" + "dCBSb290IENBIDIwMTItMS0xMRwwGgYDVQQLExNQbGF0Zm9ybSBDbG91ZFNpdGVz\n" + "MRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UEBxMLU2FuIEFudG9u\n" + "aW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzAeFw0xMjA2MDEyMDM0NDZa\n" + "Fw0xNjA1MzEyMDM0NDZaMIGNMR4wHAYDVQQDExVUZXN0IFJvb3QgQ0EgMjAxMi0x\n" + "LTExHDAaBgNVBAsTE1BsYXRmb3JtIENsb3VkU2l0ZXMxGjAYBgNVBAoTEVJhY2tz\n" + "cGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UECBMFVGV4\n" + "YXMxCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n" + "i2AMd8rFoe3Re9R0ipd2zARspYWqzOwnn2H7eqxGb08zFSQARQ/gUtl0MbNocwe0\n" + "63qEpEKJ646BKtaM/3BeH3o2ZBZoUKPl3kaietHuGM9DN9ECgftl2CeCz8OXfR92\n" + "vEUhZ/A+lep8NDqnFSXuUhgaZQOuIamrdKqjEB1THZoYNAbyfsdWC1JNv8s/S+Iq\n" + "oHCxuBaezq8CTGtNHjtwRhbSUYKzceu8Tk3ha+/d2YKubVM18mdswtNGdQau5kVI\n" + "i847TaCiBBNGE24Iei9D668nsZaDw+NpvwlJw45cBwgMnYynaF6jtgs8tE09BrnT\n" + "WcRU1DSTyHuecLS62cUwjwIDAQABozIwMDAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud\n" + "DgQWBBSk4Rk04si6m6bC0LPaIQCefbFE/DANBgkqhkiG9w0BAQUFAAOCAQEAYjcx\n" + "C28uMjWv5vguUGSr1KplxYBxecQsTtgy09gjdkpjcgznJk5yw7kri8iA/LNIzdnv\n" + "frn4ObhZrufgVoYcntAn7qA/EXrn4nnTqBzNbdclaOFKcyEjBjbdfsG0bqC0619J\n" + "EvXFvn6qTslOF5Z8icdWNBiJYNCeLAzfwsIvSWZC46bc7TuGhVpjoif80sgv48nV\n" + "DXYEevYDu2P0SQ2wAKZ0TWA4EWhI5Tra5ttpora2Bj8SFVKbz2sgr+7XLLVPJOkV\n" + "XJZb1VPAPkNFNHy0BfMlYWIFjNMSpOoWnOAdUHQGF7qFWIRK/bzH9xiAJcgyHglH\n" + "KtepHcu67ShpYsmATw==\n" + "-----END CERTIFICATE-----\n" + ""; private static final String rootSubj = "CN=Test Root CA 2012-1-1, " + "OU=Platform CloudSites, O=Rackspace Hosting, L=San Antonio, " + "ST=Texas, C=US"; private X509CertificateObject rootCrt; private KeyPair rootKey; public X509PathBuilderTest() { } @BeforeClass public static void setUpClass() { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() throws NotAnX509CertificateException, NotAnRSAKeyException { rootCrt = getCrt(rootCrtPem); rootKey = getKey(rootKeyPem); } @After public void tearDown() { } private X509CertificateObject getCrt(String crtPem) throws NotAnX509CertificateException { Object obj; NotAnX509CertificateException notCrtException = new NotAnX509CertificateException(crtPem); try { obj = PemUtils.fromPemString(crtPem); } catch (PemException ex) { throw notCrtException; } if (!(obj instanceof X509CertificateObject)) { throw notCrtException; } return (X509CertificateObject) obj; } private KeyPair getKey(String keyPem) throws NotAnRSAKeyException { Object obj; NotAnRSAKeyException notKeyException = new NotAnRSAKeyException(keyPem); try { obj = PemUtils.fromPemString(keyPem); } catch (PemException ex) { throw notKeyException; } if (!(obj instanceof KeyPair)) { throw notKeyException; } return (KeyPair) obj; } @Test public void testCreateChainBasedOnRootCa() throws NotAnX509CertificateException, RsaException { List<String> subjNames = new ArrayList<String>(); subjNames.add("O=Rackspace hosting, OU=Platform CloudSites, CN=IMD 1"); subjNames.add("O=Rackspace hosting, OU=Platform CloudSites, CN=IMD 2"); subjNames.add("O=Rackspace hosting, OU=Platform CloudSites, CN=IMD 3"); subjNames.add("O=Rackspace hosting, OU=Platform CloudSites, CN=IMD 4"); subjNames.add("O=Rackspace hosting, OU=Platform CloudSites, CN=IMD 5"); subjNames.add("O=Rackspace hosting, OU=Platform CloudSites,C=US,ST=Texas,L=San Antonio,CN=www.junit-mosso-apache2zeus-test.com"); long now = System.currentTimeMillis(); long hourAgo = 1000*60*60; long yearFromNow = 1000*60*60*24*365; int keySize = 2048; Date before = new Date(now - hourAgo); Date after = new Date(now + yearFromNow); List<X509ChainEntry> chain = X509PathBuilder.newChain(rootKey, rootCrt, subjNames, keySize, before, after); assertTrue(chain.size() == 6); for(int i=0;i<chain.size();i++){ X509Certificate x509 = (X509Certificate)chain.get(i).getX509obj(); String subj = x509.getSubjectX500Principal().getName(); String expSubj = new X509Principal(subjNames.get(i)).getName(); assertEquals(expSubj,subj); } // Verify root signatures assertTrue(CertUtils.isSelfSigned(rootCrt)); assertTrue(CertUtils.validateKeyMatchesCrt(rootKey, rootCrt).isEmpty()); assertTrue(CertUtils.validateKeySignsCert(rootKey, rootCrt).isEmpty()); assertTrue(CertUtils.verifyIssuerAndSubjectCert(rootCrt, chain.get(0).getX509obj()).isEmpty()); for(int i = 1; i< chain.size();i++){ X509CertificateObject issuerCrt = chain.get(i - 1).getX509obj(); X509CertificateObject subjectCrt = chain.get(i).getX509obj(); KeyPair issuerKey = chain.get(i - 1).getKey(); KeyPair subjectKey = chain.get(i).getKey(); // Verify subjKey matches Certs pubKey assertTrue(CertUtils.validateKeyMatchesCrt(subjectKey, subjectCrt).isEmpty()); // Verify the isser's key actually signed the subjectCrt assertTrue(CertUtils.validateKeySignsCert(issuerKey,subjectCrt).isEmpty()); // Verify the negative case that the subjCert didn't sign the root CA or something assertFalse(CertUtils.validateKeySignsCert(issuerKey,rootCrt).isEmpty()); // Verify the issuer cert signed the subject crt; assertTrue(CertUtils.verifyIssuerAndSubjectCert(issuerCrt, subjectCrt).isEmpty()); // Verify the subject cert did not sign the issuer cert. assertFalse(CertUtils.verifyIssuerAndSubjectCert(subjectCrt, issuerCrt).isEmpty()); StringBuilder pemChain = new StringBuilder(4096); for(X509ChainEntry entry : chain){ pemChain.append(PemUtils.toPemString(entry.getX509obj())); } // The users Site cert is at the end of the chain X509ChainEntry userEntry = chain.get(chain.size() - 1); KeyPair userKey = userEntry.getKey(); X509CertificateObject userCrt = userEntry.getX509obj(); PKCS10CertificationRequest userCsr = userEntry.getCsr(); System.out.printf("chain:\n%s\n\n",pemChain.toString()); System.out.printf("RootCa:\n%s\n\n", PemUtils.toPemString(rootCrt)); System.out.printf("RootKey:\n%s\n\n", PemUtils.toPemString(rootKey)); System.out.printf("userKey:\n%s\n\n",PemUtils.toPemString(userKey)); System.out.printf("userCrt:\n%s\n\n",PemUtils.toPemString(userCrt)); System.out.printf("userCsr:\n%s\n\n",PemUtils.toPemString(userCsr)); } } }