package org.openstack.atlas.util.ca.util; import org.openstack.atlas.util.ca.util.X509Inspector; import org.openstack.atlas.util.ca.util.StaticHelpers; import org.openstack.atlas.util.ca.util.PrivKeyReader; import java.io.IOException; import java.security.KeyPair; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateParsingException; import java.security.spec.InvalidKeySpecException; import java.util.logging.Level; import java.util.logging.Logger; import org.openstack.atlas.util.ca.exceptions.NotAnX509CertificateException; import org.openstack.atlas.util.ca.exceptions.PemException; import org.openstack.atlas.util.ca.exceptions.PrivKeyDecodeException; import org.openstack.atlas.util.ca.exceptions.RsaException; import org.openstack.atlas.util.ca.primitives.RsaConst; import org.openstack.atlas.util.ca.util.PrivKeyReaderTest; import java.math.BigInteger; import java.security.cert.X509Certificate; import java.util.Date; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.Assert; import org.openstack.atlas.util.ca.CertUtils; import org.openstack.atlas.util.ca.exceptions.CapManUtilException; import org.openstack.atlas.util.ca.exceptions.X509ReaderDecodeException; import org.openstack.atlas.util.ca.exceptions.X509ReaderNoSuchExtensionException; public class X509InspectorTest { public static final BigInteger caMod = new BigInteger("92519081613557335824146312114331099693596712334582852764163758222004945339138079274569160547038643263700275407813235096605105941298720472784518757878492358916313599921202611417629889327386843437793899506223684027421621426615502802714869767807708103437254423295282076493912484979373100387883795899165798220483"); public static final String caSubjId = "a72ad48c3632e4f3f0381b48474abe7126530dd8"; public static final BigInteger testMod = new BigInteger("92769520113997379614084710552346480125314109559245447551856686347298813937630358936531128096799589632829885895580345157680107273222950724084624729121336709416739678416576244399370216587550882915851315377147000246928233006530724331354867197205185517189113923758771082160421912659909039341373309420290932945177"); public static final String testCrtSubjKeyId = "607cc6865330a280efdf3d1ca865e79acd745b55"; public static final String pkcs8CrtPem = "-----BEGIN CERTIFICATE-----\n" + "MIIDOzCCAqSgAwIBAgIGATbnee+RMA0GCSqGSIb3DQEBBQUAMHYxEDAOBgNVBAMT\n" + "B1Rlc3QgQ0ExGzAZBgNVBAsTElJhY2tzcGFjZSBQbGF0Zm9ybTESMBAGA1UEChMJ\n" + "UmFja3NwYWNlMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UECBMFVGV4YXMx\n" + "CzAJBgNVBAYTAlVTMB4XDTEyMDQyNTAzMDk0OVoXDTE2MDIyNDAzMDk0OVowdjEL\n" + "MAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYDVQQHEwtTYW4gQW50b25p\n" + "bzERMA8GA1UEChMIVGVzdCBPcmcxFjAUBgNVBAsTDVRlc3QgT3JnIFVuaXQxFjAU\n" + "BgNVBAMTDXd3dy5wa2NzOC5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB\n" + "AI3xVCC2rx2KTTyutHLEKpc5/wkU8hkJ1lSqbKoJsuC5fw24Nzw/OmJDSJBHF3Pf\n" + "7Z6mVWy+BKXHhiJ8mgkJ9CY97FxrUy/hkPuBwkhcmmPlKO9JOmfP/2MSXLoawsmo\n" + "yaQ7jRs2+euoD1bj/9yM2KIWMIGphEtIN99Kr8LZX1WlAgMBAAGjgdMwgdAwDAYD\n" + "VR0TAQH/BAIwADCBoAYDVR0jBIGYMIGVgBSnKtSMNjLk8/A4G0hHSr5xJlMN2KF6\n" + "pHgwdjEQMA4GA1UEAxMHVGVzdCBDQTEbMBkGA1UECxMSUmFja3NwYWNlIFBsYXRm\n" + "b3JtMRIwEAYDVQQKEwlSYWNrc3BhY2UxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\n" + "DAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVOCAQEwHQYDVR0OBBYEFHNn39xsWJQk\n" + "cVREN2P71uI/7O3CMA0GCSqGSIb3DQEBBQUAA4GBAHFYGY+kHS6IwOnq/1oNgqwE\n" + "lPa5pYVMmAB8WwqIUzOUMmhwAKeG8p8YYZ6VlvSvuHDjdhgwIy1oA1q21b2Hx7Ka\n" + "hjBuRVPLC5kwhlcij7ZLTJ9xSj3M7Bmn8yWJIsr5UD2LEDylFsy4l7VvsXSvTUjm\n" + "heVVwQ4IvpsvboMQS4uY\n" + "-----END CERTIFICATE-----\n"; public static final String caCrtPem = "-----BEGIN CERTIFICATE-----\n" + "MIIClDCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQUFADB2MRAwDgYDVQQDEwdUZXN0\n" + "IENBMRswGQYDVQQLExJSYWNrc3BhY2UgUGxhdGZvcm0xEjAQBgNVBAoTCVJhY2tz\n" + "cGFjZTEUMBIGA1UEBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYD\n" + "VQQGEwJVUzAeFw0xMjA0MjQyMjA2MzhaFw0zOTA5MTAyMjA2MzhaMHYxEDAOBgNV\n" + "BAMTB1Rlc3QgQ0ExGzAZBgNVBAsTElJhY2tzcGFjZSBQbGF0Zm9ybTESMBAGA1UE\n" + "ChMJUmFja3NwYWNlMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UECBMFVGV4\n" + "YXMxCzAJBgNVBAYTAlVTMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDwGVJ\n" + "6fe+iXCVzCcGWc4XcNgoa3R/2YW9fsV8FKfan/6UfeDxYwb7MeDtHg7VFawLLUMr\n" + "StOEN2ZKcYsQxsMS65P4lrxrSMSU7F6HtVZMB+XVYe4UeUSVo03MN8t6l9a3/A0b\n" + "ga16/SdBqZ91P9BO0IAtxcIyk2m/cYKopDrCwwIDAQABozIwMDAPBgNVHRMBAf8E\n" + "BTADAQH/MB0GA1UdDgQWBBSnKtSMNjLk8/A4G0hHSr5xJlMN2DANBgkqhkiG9w0B\n" + "AQUFAAOBgQAIvAB4WsQzdg89XSYS5kZy1hC2u834MQG7aUegl93TzesdJI4/Iw6H\n" + "E/vlASKYy/hCX8ZKv1c9yXKc2hejJ7IUiKRzk5R8WS0yJ6VDlMNDmsDCpGfaEMj1\n" + "M08azGyscfqJooKQc57Q9fn22PVt/vVdOVr9rQEIBKrPMj3tZKu6dw==\n" + "-----END CERTIFICATE-----\n"; public static final String testCrtPem = "-----BEGIN CERTIFICATE-----\n" + "MIIDQzCCAqygAwIBAgIGATbmZcRlMA0GCSqGSIb3DQEBBQUAMHYxEDAOBgNVBAMT\n" + "B1Rlc3QgQ0ExGzAZBgNVBAsTElJhY2tzcGFjZSBQbGF0Zm9ybTESMBAGA1UEChMJ\n" + "UmFja3NwYWNlMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UECBMFVGV4YXMx\n" + "CzAJBgNVBAYTAlVTMB4XDTEyMDQyNDIyMDgxMFoXDTE2MDQyMzIyMDgxMFowezEL\n" + "MAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYDVQQHEwtTYW4gQW50b25p\n" + "bzESMBAGA1UEChMJUmFja3NwYWNlMRswGQYDVQQLExJSYWNrc3BhY2UgUGxhdGZv\n" + "cm0xFTATBgNVBAMTDHd3dy50ZXN0Lm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw\n" + "gYkCgYEAhBuxzYbl9FSyiGDkGoIbAOhyUmeJ0QAn8cs10l9ysg5UWDPaRhYybaDI\n" + "NrrDRJynrH4Tpgl32HoVzMI99+E9/PGKLvi3HTxI9hSkRNJKaN3PFcYIwlS4Ex50\n" + "Ju+8LfzBBmwoYwJCa889oJOmMEOpyV+da48LyMd0a/rX2/4vMRkCAwEAAaOB1jCB\n" + "0zAPBgNVHRMBAf8EBTADAQH/MIGgBgNVHSMEgZgwgZWAFKcq1Iw2MuTz8DgbSEdK\n" + "vnEmUw3YoXqkeDB2MRAwDgYDVQQDEwdUZXN0IENBMRswGQYDVQQLExJSYWNrc3Bh\n" + "Y2UgUGxhdGZvcm0xEjAQBgNVBAoTCVJhY2tzcGFjZTEUMBIGA1UEBxMLU2FuIEFu\n" + "dG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAdBgNVHQ4EFgQU\n" + "YHzGhlMwooDv3z0cqGXnms10W1UwDQYJKoZIhvcNAQEFBQADgYEASQgzb+VgnENQ\n" + "gMPO4Otl9TSEMgaKbPG9zpt/lHrRQPpxiOc/v9Cu4Re3cIRZbI6NV9kAdAOu9I1N\n" + "kEnLnXeZT36K/uRHIbgBrzYRAE1ZNnYRcqnUKJjzBC5i+hIYAme1+TGC0D5bP3nK\n" + "HHt/1nKUQmnEVy+LhqdDCwDCNmGvPZI=\n" + "-----END CERTIFICATE-----\n"; private static final String caSubj = "CN=TestCa,OU=someOrgUnit,O=SomeOrg" + ",L=San Antonio,ST=Texas,C=US"; private X509Inspector caCrtReader; private X509Inspector testCrtReader; private X509Inspector pkcs8CrtReader; private PrivKeyReader caKeyReader; private PrivKeyReader testKeyReader; private PrivKeyReader key2048bitReader; public X509InspectorTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() throws X509ReaderDecodeException, NotAnX509CertificateException, PrivKeyDecodeException { RsaConst.init(); caCrtReader = X509Inspector.newX509Inspector(caCrtPem); caKeyReader = PrivKeyReader.newPrivKeyReader(PrivKeyReaderTest.caKeyPem); testCrtReader = X509Inspector.newX509Inspector(testCrtPem); testKeyReader = PrivKeyReader.newPrivKeyReader(PrivKeyReaderTest.testKeyPem); pkcs8CrtReader = X509Inspector.newX509Inspector(pkcs8CrtPem); key2048bitReader = PrivKeyReader.newPrivKeyReader(PrivKeyReaderTest.key2048bit); } @After public void tearDown() { } @Test public void caCrtShouldModMatchCaKey() { BigInteger crtMod = caCrtReader.getPubModulus(); BigInteger keyMod = caKeyReader.getN(); Assert.assertEquals(keyMod, crtMod); Assert.assertEquals(keyMod, caMod); } @Test public void keyShouldModMatchWithTestCrt() { BigInteger crtMod = testCrtReader.getPubModulus(); BigInteger keyMod = testKeyReader.getN(); Assert.assertEquals(crtMod, keyMod); Assert.assertEquals(crtMod, testMod); } @Test public void shouldGetCorrectCN() throws X509ReaderDecodeException { Assert.assertEquals("Test CA", caCrtReader.getSubjectCN()); Assert.assertEquals("Test CA", caCrtReader.getIssuerCN()); // This caCrt was self signed. LOL Assert.assertEquals("www.test.org", testCrtReader.getSubjectCN()); Assert.assertEquals("Test CA", caCrtReader.getIssuerCN()); Assert.assertEquals("www.pkcs8.org", pkcs8CrtReader.getSubjectCN()); } @Test public void shouldGetCorrectSerials() { Assert.assertEquals(BigInteger.ONE, caCrtReader.getSerial()); Assert.assertEquals("136e665c465", testCrtReader.getSerial().toString(16)); } @Test public void shouldGetCorrectKeyIds() throws X509ReaderNoSuchExtensionException, X509ReaderDecodeException { Assert.assertEquals(caCrtReader.getSubjKeyId(), caSubjId); Assert.assertEquals(testCrtSubjKeyId, testCrtReader.getSubjKeyId()); Assert.assertEquals(testCrtReader.getAuthKeyId(), caCrtReader.getSubjKeyId()); // They should match since CA signed testCrt; } @Test public void shouldGetNullIfKeyIdDoesNotExist() { Assert.assertNull(caCrtReader.getAuthKeyId()); } @Test public void shouldRecognizePrematureCert() throws CapManUtilException, InvalidKeySpecException { Assert.assertTrue(qXR(bef(2040, 1, 1), aft(2048, 1, 1)).isPremature(null)); Assert.assertFalse(qXR(bef(2012, 5, 21), aft(2048, 1, 1)).isPremature(null)); Assert.assertFalse(qXR(bef(2005, 1, 1), aft(2006, 1, 1)).isPremature(null)); Assert.assertTrue(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isPremature(now(2011, 12, 31))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isPremature(now(2012, 1, 1))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isPremature(now(2012, 5, 28))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isPremature(now(2013, 1, 1))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isPremature(now(2013, 6, 28))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isPremature(now(2014, 6, 28))); } @Test public void shouldRecognizeExpiredCert() throws CapManUtilException, InvalidKeySpecException { Assert.assertFalse(qXR(bef(2040, 1, 1), aft(2048, 1, 1)).isExpired(null)); Assert.assertFalse(qXR(bef(2012, 5, 21), aft(2048, 1, 1)).isExpired(null)); Assert.assertTrue(qXR(bef(2005, 1, 1), aft(2006, 1, 1)).isExpired(null)); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isExpired(now(2011, 12, 31))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isExpired(now(2012, 1, 1))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isExpired(now(2012, 5, 28))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isExpired(now(2013, 1, 1))); Assert.assertTrue(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isExpired(now(2013, 6, 28))); Assert.assertTrue(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isExpired(now(2014, 6, 28))); } @Test public void shouldRecognizeInRangeCerts() throws CapManUtilException, InvalidKeySpecException { Assert.assertFalse(qXR(bef(2040, 1, 1), aft(2048, 1, 1)).isDateValid(null)); Assert.assertTrue(qXR(bef(2012, 5, 21), aft(2048, 1, 1)).isDateValid(null)); Assert.assertFalse(qXR(bef(2005, 1, 1), aft(2006, 1, 1)).isDateValid(null)); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isDateValid(now(2011, 12, 31))); Assert.assertTrue(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isDateValid(now(2012, 1, 1))); Assert.assertTrue(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isDateValid(now(2012, 5, 28))); Assert.assertTrue(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isDateValid(now(2013, 1, 1))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isDateValid(now(2013, 6, 28))); Assert.assertFalse(qXR(bef(2012, 1, 1), aft(2013, 1, 1)).isDateValid(now(2014, 6, 28))); } public void testRootCa() { System.out.printf("%s\n\n%s\n\n%s\n\n", caCrtPem, caCrtPem, caCrtPem); System.out.printf("%s\n\n%s\n\n%s\n\n", caCrtPem, caCrtPem, caCrtPem); System.out.printf("%s\n\n%s\n\n%s\n\n", caCrtPem, caCrtPem, caCrtPem); System.out.printf("%s\n\n%s\n\n%s\n\n", caCrtPem, caCrtPem, caCrtPem); } private static Date now(int... tup) { return StaticHelpers.dateFromTuple(tup); } private static Date bef(int... tup) { return StaticHelpers.dateFromTuple(tup); } private static Date aft(int... tup) { return qDT(tup); } private static Date qDT(int... tup) { return StaticHelpers.dateFromTuple(tup); } private X509Inspector qXR(Date notBefore, Date notAfter) throws CapManUtilException, InvalidKeySpecException { KeyPair kp = key2048bitReader.toKeyPair(); X509Certificate x509 = CertUtils.quickSelfSign(kp, caSubj, notBefore, notAfter); X509Inspector xr; try { xr = X509Inspector.newX509Inspector(x509); } catch (CertificateEncodingException ex) { throw new CapManUtilException(ex); } catch (CertificateParsingException ex) { throw new CapManUtilException(ex); } catch (NotAnX509CertificateException ex) { throw new CapManUtilException(ex); } return xr; } }