Java tutorial
/* * Copyright (c) 2008-2012, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Eclipse Public License, * tyrex license, freemarker license, dom4j license, mx4j license, * Spice Software License, Common Development and Distribution License * (CDDL), Common Public License (CPL) the licensors of this Program grant * you additional permission to convey the resulting work. */ package mitm.common.security.crl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.KeyFactory; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Date; import mitm.common.security.KeyAndCertificateImpl; import mitm.common.security.SecurityFactory; import mitm.common.security.SecurityFactoryFactory; import mitm.test.TestUtils; import org.apache.commons.codec.binary.Hex; import org.apache.commons.io.IOUtils; import org.apache.log4j.PropertyConfigurator; import org.bouncycastle.asn1.x509.CRLReason; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.BeforeClass; import org.junit.Test; public class GenerateTestCRLs { private static SecurityFactory securityFactory; private static X509Certificate caCertificate; private static PrivateKey caPrivateKey; private static X509Certificate rootCertificate; private static PrivateKey rootPrivateKey; @BeforeClass public static void setUpBeforeClass() throws Exception { PropertyConfigurator.configure("conf/log4j.properties"); securityFactory = SecurityFactoryFactory.getSecurityFactory(); loadCA(); } private static void loadCA() throws Exception { KeyStore caKeyStore = securityFactory.createKeyStore("PKCS12"); File file = new File("test/resources/testdata/keys/testCA.p12"); FileInputStream input = new FileInputStream(file); caKeyStore.load(input, "test".toCharArray()); caCertificate = (X509Certificate) caKeyStore.getCertificate("ca"); caPrivateKey = (PrivateKey) caKeyStore.getKey("ca", null); rootCertificate = (X509Certificate) caKeyStore.getCertificate("root"); rootPrivateKey = (PrivateKey) caKeyStore.getKey("root", null); assertNotNull(caCertificate); assertNotNull(caPrivateKey); } private PrivateKey decodePrivateKey(String encoded) throws Exception { byte[] rawKey = Hex.decodeHex(encoded.toCharArray()); KeySpec keySpec = new PKCS8EncodedKeySpec(rawKey); KeyFactory keyFactory = securityFactory.createKeyFactory("RSA"); return keyFactory.generatePrivate(keySpec); } private X509CRLBuilder createX509CRLBuilder() { return new X509CRLBuilderImpl(BouncyCastleProvider.PROVIDER_NAME, BouncyCastleProvider.PROVIDER_NAME); } @Test public void testGenerateCACRL() throws Exception { X509CRLBuilder crlGenerator = createX509CRLBuilder(); Date thisDate = TestUtils.parseDate("30-Nov-2007 11:38:35 GMT"); Date nextDate = TestUtils.parseDate("30-Nov-2027 11:38:35 GMT"); crlGenerator.setThisUpdate(thisDate); crlGenerator.setNextUpdate(nextDate); crlGenerator.setSignatureAlgorithm("SHA256WithRSAEncryption"); X509Certificate certificate = TestUtils .loadCertificate("test/resources/testdata/certificates/" + "valid_certificate_mitm_test_ca.cer"); assertNotNull(certificate); crlGenerator.addCRLEntry(certificate.getSerialNumber(), thisDate, CRLReason.privilegeWithdrawn); X509CRL crl = crlGenerator.generateCRL(new KeyAndCertificateImpl(caPrivateKey, caCertificate)); assertEquals("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL", crl.getIssuerX500Principal().toString()); assertEquals(thisDate, crl.getThisUpdate()); assertEquals(nextDate, crl.getNextUpdate()); assertEquals(1, crl.getRevokedCertificates().size()); assertTrue(crl.isRevoked(certificate)); File crlFile = new File("test/tmp/test-generate-ca.crl"); FileOutputStream fos = new FileOutputStream(crlFile); IOUtils.write(crl.getEncoded(), fos); fos.close(); } @Test public void testGenerateCACRLThisUpdateInFarFuture() throws Exception { X509CRLBuilder crlGenerator = createX509CRLBuilder(); Date thisDate = TestUtils.parseDate("30-Nov-2030 11:38:35 GMT"); Date nextDate = TestUtils.parseDate("30-Nov-2040 11:38:35 GMT"); crlGenerator.setThisUpdate(thisDate); crlGenerator.setNextUpdate(nextDate); crlGenerator.setSignatureAlgorithm("SHA256WithRSAEncryption"); X509Certificate certificate = TestUtils .loadCertificate("test/resources/testdata/certificates/" + "valid_certificate_mitm_test_ca.cer"); assertNotNull(certificate); Date revocationDate = TestUtils.parseDate("30-Nov-2006 11:38:35 GMT"); crlGenerator.addCRLEntry(certificate.getSerialNumber(), revocationDate, CRLReason.keyCompromise); X509CRL crl = crlGenerator.generateCRL(new KeyAndCertificateImpl(caPrivateKey, caCertificate)); assertEquals("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL", crl.getIssuerX500Principal().toString()); assertEquals(thisDate, crl.getThisUpdate()); assertEquals(nextDate, crl.getNextUpdate()); assertEquals(1, crl.getRevokedCertificates().size()); assertTrue(crl.isRevoked(certificate)); File crlFile = new File("test/tmp/testgeneratecacrlthisupdateinfarfuture.crl"); FileOutputStream fos = new FileOutputStream(crlFile); IOUtils.write(crl.getEncoded(), fos); fos.close(); } @Test public void testGenerateCACRLSignedByIncorrectKey() throws Exception { X509CRLBuilder crlGenerator = createX509CRLBuilder(); Date thisDate = TestUtils.parseDate("30-Nov-2007 11:38:35 GMT"); Date nextDate = TestUtils.parseDate("30-Nov-2027 11:38:35 GMT"); crlGenerator.setThisUpdate(thisDate); crlGenerator.setNextUpdate(nextDate); crlGenerator.setSignatureAlgorithm("SHA256WithRSAEncryption"); X509Certificate certificate = TestUtils .loadCertificate("test/resources/testdata/certificates/" + "valid_certificate_mitm_test_ca.cer"); assertNotNull(certificate); crlGenerator.addCRLEntry(certificate.getSerialNumber(), thisDate, CRLReason.privilegeWithdrawn); String encodedPrivateKey = "30820276020100300d06092a864886f70d0101010500048202603082025c" + "02010002818100a9fee3017954c99b248d1486830c71b2e0ea3f9b7a2763" + "1bed8a731f5bd7e1edf856bc3fb7c63dedbeb5bb0de474e7792b3aa7e7b2" + "274c03a47c7d89b1935eaef172c6395f2322f1ed9e61ae46d716b4b4394c" + "1a802db05a2d7c3d1d41a3e8afc65ff8dada7414744f1ee1540e50ee7fb8" + "db437b20c5ee33a82b9d575cfbc951020301000102818004f84ab2b45562" + "3f82e60cff91bd3f65b765a1ce6dd7d0f1f413e421ba91a92d47e161478b" + "9be41b9b43bce03f199bdad304b7fbf21d6bff7f439477fe150ce38c312f" + "c015f3c89291aaa42c4c106f623dfd9f76acad2f1c77b590f038ffbb25f9" + "14b6f7ead769808ddd0e2d648442620b50518d9b7fb132b2fa1fa3e9d628" + "41024100e69ab3765120d0e0ba5dc21bf384b2f553211b4b1902175454c6" + "2f1b0f8ad385d78490539308c9fd5145ae36cc2a6d364fdd97d83d9b6623" + "a987db239e716055024100bcb77acf1e9829ab5b2c9a5e73d343db857474" + "a529ba52ca256655eb7d760e85d3c68eec9500e3db0494c8f77cb8058593" + "6e52a9290149367392d74ecdc3510d024100bd15723b7cb024b56ffabad3" + "c26c3774f2b1bdb8690c0ee7060feec6088b737f56450b368be4740332e5" + "a8c0a3cdd1f8eba9adfd101ee0b43329036584604075024055465b9a27ea" + "fe394e33b375a6c4fa4ec1d943b4364cd9883aaa297d05ee48d5b4426ee6" + "fcd5b02091cb619c63a10bedb6170e071e5e5464e4889ffe1e007a290240" + "7b60d23994a2ec38db909678446ed56d32455bf684141b9ee0aec68b2025" + "1d4d94fd2beebf02074559b811ae1130d2e2aa3bec2e9bccb06969104856" + "00c70759"; PrivateKey privateKey = decodePrivateKey(encodedPrivateKey); // sign not by the caPrivateKey but by some other key X509CRL crl = crlGenerator.generateCRL(new KeyAndCertificateImpl(privateKey, caCertificate)); assertEquals("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL", crl.getIssuerX500Principal().toString()); assertEquals(thisDate, crl.getThisUpdate()); assertEquals(nextDate, crl.getNextUpdate()); assertEquals(1, crl.getRevokedCertificates().size()); assertTrue(crl.isRevoked(certificate)); File crlFile = new File("test/tmp/test-generate-ca-signed-incorrect-key.crl"); FileOutputStream fos = new FileOutputStream(crlFile); IOUtils.write(crl.getEncoded(), fos); fos.close(); } @Test public void testGenerateCACRLNoNextUpdate() throws Exception { X509CRLBuilder crlGenerator = createX509CRLBuilder(); Date thisDate = TestUtils.parseDate("30-Nov-2007 11:38:35 GMT"); crlGenerator.setThisUpdate(thisDate); crlGenerator.setSignatureAlgorithm("SHA256WithRSAEncryption"); X509Certificate certificate = TestUtils .loadCertificate("test/resources/testdata/certificates/" + "valid_certificate_mitm_test_ca.cer"); assertNotNull(certificate); crlGenerator.addCRLEntry(certificate.getSerialNumber(), thisDate, CRLReason.privilegeWithdrawn); X509CRL crl = crlGenerator.generateCRL(new KeyAndCertificateImpl(caPrivateKey, caCertificate)); assertEquals("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL", crl.getIssuerX500Principal().toString()); assertEquals(thisDate, crl.getThisUpdate()); assertEquals(null, crl.getNextUpdate()); assertEquals(1, crl.getRevokedCertificates().size()); assertTrue(crl.isRevoked(certificate)); File crlFile = new File("test/tmp/test-generate-ca-no-next-update.crl"); FileOutputStream fos = new FileOutputStream(crlFile); IOUtils.write(crl.getEncoded(), fos); fos.close(); } @Test public void testGenerateRootEmptyCRL() throws Exception { X509CRLBuilder crlGenerator = createX509CRLBuilder(); Date thisDate = TestUtils.parseDate("30-Nov-2007 11:38:35 GMT"); Date nextDate = TestUtils.parseDate("30-Nov-2027 11:38:35 GMT"); crlGenerator.setThisUpdate(thisDate); crlGenerator.setNextUpdate(nextDate); crlGenerator.setSignatureAlgorithm("SHA256WithRSAEncryption"); X509CRL crl = crlGenerator.generateCRL(new KeyAndCertificateImpl(rootPrivateKey, rootCertificate)); assertEquals("EMAILADDRESS=root@example.com, CN=MITM Test Root, L=Amsterdam, ST=NH, C=NL", crl.getIssuerX500Principal().toString()); assertEquals(thisDate, crl.getThisUpdate()); assertEquals(nextDate, crl.getNextUpdate()); assertNull(crl.getRevokedCertificates()); assertFalse(crl.isRevoked(caCertificate)); File crlFile = new File("test/tmp/test-generate-root-empty.crl"); FileOutputStream fos = new FileOutputStream(crlFile); IOUtils.write(crl.getEncoded(), fos); fos.close(); } @Test public void testGenerateRootRevokedCRL() throws Exception { X509CRLBuilder crlGenerator = createX509CRLBuilder(); Date thisDate = TestUtils.parseDate("30-Nov-2007 11:38:35 GMT"); Date nextDate = TestUtils.parseDate("30-Nov-2027 11:38:35 GMT"); crlGenerator.setThisUpdate(thisDate); crlGenerator.setNextUpdate(nextDate); crlGenerator.setSignatureAlgorithm("SHA256WithRSAEncryption"); crlGenerator.addCRLEntry(caCertificate.getSerialNumber(), thisDate, CRLReason.cACompromise); X509CRL crl = crlGenerator.generateCRL(new KeyAndCertificateImpl(rootPrivateKey, rootCertificate)); assertEquals("EMAILADDRESS=root@example.com, CN=MITM Test Root, L=Amsterdam, ST=NH, C=NL", crl.getIssuerX500Principal().toString()); assertEquals(thisDate, crl.getThisUpdate()); assertEquals(nextDate, crl.getNextUpdate()); assertEquals(1, crl.getRevokedCertificates().size()); assertTrue(crl.isRevoked(caCertificate)); File crlFile = new File("test/tmp/test-generate-root-ca-revoked.crl"); FileOutputStream fos = new FileOutputStream(crlFile); IOUtils.write(crl.getEncoded(), fos); fos.close(); } }