From 0bcc057e741af3fbc108f42b75f9d42f48f6a51e Mon Sep 17 00:00:00 2001 From: Yuuta Liang Date: Sat, 14 Oct 2023 05:12:06 +0800 Subject: Implement the CA Signed-off-by: Yuuta Liang --- src/test/model/TestConstants.java | 4 +- src/test/model/asn1/IntTest.java | 3 + src/test/model/ca/AuditLogEntryTest.java | 26 ++++ src/test/model/ca/CACertificateTest.java | 178 ++++++++++++++++++++++++ src/test/model/ca/TemplateTest.java | 27 ++++ src/test/model/pki/cert/TbsCertificateTest.java | 12 ++ 6 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 src/test/model/ca/AuditLogEntryTest.java create mode 100644 src/test/model/ca/CACertificateTest.java create mode 100644 src/test/model/ca/TemplateTest.java (limited to 'src/test/model') diff --git a/src/test/model/TestConstants.java b/src/test/model/TestConstants.java index 3356549..f0ba35a 100644 --- a/src/test/model/TestConstants.java +++ b/src/test/model/TestConstants.java @@ -505,8 +505,8 @@ public final class TestConstants { TestConstants.REVOKED_KEY_COMPROMISE }); CRL_CONTENT_1_DER = combine((byte) 0x30, CRL_CONTENT_1.getVersion().encodeDER(), - CRL_CONTENT_1.getIssuer().encodeDER(), CRL_CONTENT_1.getSignature().encodeDER(), + CRL_CONTENT_1.getIssuer().encodeDER(), CRL_CONTENT_1.getThisUpdate().encodeDER(), combine((byte) 0x30, REVOKED_CESSATION_DER, REVOKED_KEY_COMPROMISE_DER)); CRL_CONTENT_2 = new CertificateListContent(CRL_CONTENT_1.getTag(), CRL_CONTENT_1.getParentTag(), @@ -516,8 +516,8 @@ public final class TestConstants { CRL_CONTENT_1.getThisUpdate(), CRL_CONTENT_1.getRevokedCertificates()); CRL_CONTENT_2_DER = combine((byte) 0x30, CRL_CONTENT_2.getVersion().encodeDER(), - CRL_CONTENT_2.getIssuer().encodeDER(), CRL_CONTENT_2.getSignature().encodeDER(), + CRL_CONTENT_2.getIssuer().encodeDER(), CRL_CONTENT_2.getThisUpdate().encodeDER(), CRL_CONTENT_2.getNextUpdate().encodeDER(), combine((byte) 0x30, REVOKED_CESSATION_DER, REVOKED_KEY_COMPROMISE_DER)); diff --git a/src/test/model/asn1/IntTest.java b/src/test/model/asn1/IntTest.java index 6e92eb0..23a5e23 100644 --- a/src/test/model/asn1/IntTest.java +++ b/src/test/model/asn1/IntTest.java @@ -4,6 +4,8 @@ import model.asn1.exceptions.ParseException; import model.asn1.parsing.BytesReader; import org.junit.jupiter.api.Test; +import java.math.BigInteger; + import static org.junit.jupiter.api.Assertions.*; public class IntTest { @@ -11,6 +13,7 @@ public class IntTest { void testConstructor() { assertEquals(0x2, new Int(Int.TAG, null, 255).getTag().getNumber()); assertEquals(255, new Int(Int.TAG, null, 255).getLong()); + assertEquals(255, new Int(Int.TAG, null, BigInteger.valueOf(255)).getLong()); } @Test diff --git a/src/test/model/ca/AuditLogEntryTest.java b/src/test/model/ca/AuditLogEntryTest.java new file mode 100644 index 0000000..af44947 --- /dev/null +++ b/src/test/model/ca/AuditLogEntryTest.java @@ -0,0 +1,26 @@ +package model.ca; + +import org.junit.jupiter.api.Test; + +import java.time.ZonedDateTime; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AuditLogEntryTest { + @Test + void testConstructor() { + ZonedDateTime now = ZonedDateTime.now(); + AuditLogEntry entry = new AuditLogEntry("user", now, "action123"); + assertEquals("user", entry.getUser()); + assertEquals(now, entry.getTime()); + assertEquals("action123", entry.getAction()); + } + + @Test + void testToString() { + ZonedDateTime now = ZonedDateTime.now(); + AuditLogEntry entry = new AuditLogEntry("user", now, "action123"); + assertEquals(now + "\tuser\taction123", + entry.toString()); + } +} diff --git a/src/test/model/ca/CACertificateTest.java b/src/test/model/ca/CACertificateTest.java new file mode 100644 index 0000000..4db7bf4 --- /dev/null +++ b/src/test/model/ca/CACertificateTest.java @@ -0,0 +1,178 @@ +package model.ca; + +import model.TestConstants; +import model.asn1.ASN1Object; +import model.asn1.ObjectIdentifier; +import model.asn1.UtcTime; +import model.asn1.parsing.BytesReader; +import model.csr.CertificationRequest; +import model.csr.CertificationRequestInfo; +import model.pki.cert.Certificate; +import model.pki.crl.Reason; +import model.pki.crl.RevokedCertificate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ui.Utils; + +import java.nio.charset.StandardCharsets; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import static org.junit.jupiter.api.Assertions.*; + +public class CACertificateTest { + private static final String CA = "-----BEGIN CERTIFICATE-----\n" + + "MIIC3zCCAoagAwIBAgIUWcL8J0hbxGSffN0fR76j8TlGxJswCgYIKoZIzj0EAwQw\n" + + "JDEVMBMGA1UEAwwMVGVzdCBSb290IENBMQswCQYDVQQGEwJDQTAeFw0yMzEwMTMw\n" + + "MTQ3MzFaFw0zMzEwMTAwMTQ3MzFaMA4xDDAKBgNVBAMTA0pDQTCCASIwDQYJKoZI\n" + + "hvcNAQEBBQADggEPADCCAQoCggEBAINbCR88MTUsx/poxNzXxN1aWt/DkkFrRA3r\n" + + "dHmLXQLjopULgHIJTshSq2jDe1QEYJ0Nrj9U9YclmxkWO0HvzedmTyl0YzAhPJXj\n" + + "HUK0T9sYSg+eE4WI03yuy7lGBJLUl9VEBR0JEZdy/mT5CRW44ryGGeeBNK3fqQrk\n" + + "5Rm9/wY5M2cKjYmvyp5D8E+HEd+FXNreO+r9pWpKSajPn+B6OwFUUESbRf8iWiF4\n" + + "v6ZLXDOBCEHFZcd2lTVHExuE+V3eDG3evn8HV5SB7FzRDZBV2Jz0Pfiqu2WlH4r8\n" + + "c1804G4WCjQlSX4bPs7994+KjUoFC95r40vexi2O9mVIIEF4LtkCAwEAAaOB4DCB\n" + + "3TAdBgNVHQ4EFgQU+c9PnChWwj4sWHFMN/dikzOS5o8wHwYDVR0jBBgwFoAUba4m\n" + + "yCy2hdnsc6Hhw4m8dvIbit0wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E\n" + + "BAMCAYYwNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2hvbWUueXV1dGEubW9lL3Br\n" + + "aS9yb290Y2EuY3JsMEAGCCsGAQUFBwEBBDQwMjAwBggrBgEFBQcwAoYkaHR0cDov\n" + + "L2hvbWUueXV1dGEubW9lL3BraS9yb290Y2EuY3J0MAoGCCqGSM49BAMEA0cAMEQC\n" + + "IETA9hpUnbrWpLfu2HUWr9UQC273jyg/nt30rJ96PNS+AiAsNzbKVyBpkG41Hf1/\n" + + "+355E7vortNonvf0DDGJZjC7MA==\n" + + "-----END CERTIFICATE-----"; + + private static final String CSR = "-----BEGIN CERTIFICATE REQUEST-----\n" + + "MIIEZjCCAk4CAQAwITELMAkGA1UEBhMCQ0ExEjAQBgNVBAMMCVRlc3QgTGVhZjCC\n" + + "AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYDEoMbxZEuerV5G9IXUXfe\n" + + "UB3u3Yf4b9QI7ewea3Vw04eS/XY4J/KC58OAKc+/3B0Vjghza1+bMalkdFHuIYls\n" + + "/57wbmKIoRSZouma31gHJATWPdDpzcAeZVGRfqfniw3dDfVpIea5gi63gmTFGD7l\n" + + "rmdn5BhQBijWXQY5gD52vGmnalqPBBL+HXgynYiTxmoGI/UNW16V1k8OTnT2F3kt\n" + + "OES+5/mu2r4c7fExmkh64wXYqL2EUvh7xvd4KKIh05Bsl5J2G0Lkl1gh89FJHOVW\n" + + "5+jrMku1wU4KBSZWNvxgcSgfKOI3IAx6iqxflhb7FKK3VTYZ7zJ/cAhaJvv1gJ7N\n" + + "S5AlxsFxMRMgLoFtad9Qk5wH+wX+9Ozf7jNoWZQnLgzfr7CdvjBPmYR/THg0OWFS\n" + + "0bkr20G8lMvtGMbmjN6Ot70KzYCIDjaCV5sX60i76p7rSheibgCslO49cRU7G266\n" + + "HB1GXZNQbT3xBzoaVN9B5uQnL8tUnTn0PsQ4KN2MKIfQt+IO0yesBI7yjXRHSOJX\n" + + "WmbZnrojfYbyAWPBKXnQ4vFcqBdXIXGuI4f67Y8BBuJjV9FOUxcCu++ypP2RtS8h\n" + + "sly2wgtRwPCN7BbLOY9A7qm821DJ3MneHKloGodNvcBvq9VLcwFA9QFX5tgnETV8\n" + + "4oc0VHxaiB7zuNchjINFAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEAiRKUSg4m\n" + + "i+qozc3Nx80LfCO9b4+oWp7/bcv0fUADfet7nsobwY8Y6INYMEs6aBNnj2ofFmEd\n" + + "Kup3VHh3vce7Grwkn0MWXKRdCbsLVJ5joWixxxbCDgiRZLYDVlhnU7ZFm3mxmC4l\n" + + "KfKMiHfW833gnemQYRAyamDErKgPV8O9spm0TLj2nLllcA5ugR98kh9TnvnQqRdq\n" + + "dO0ic8C2OECRPV9OVmP13qXiVJRApWYBrw+WJT+sz3LRGfQMIzaTPYWen0dd8+iG\n" + + "HhJot7DNbdLMf6jtWXazrsmUhjjgr5KHMZdOWcbqBCRZkVTkf1HfoRbBTt/wEkBX\n" + + "fJrXVpGbA7H7xXDXKFVUM19q7JJr9M5CfAvCtUGg/UnqfhDnqsFHgQqro21YwNQP\n" + + "/bahU44eNoz8RUiyDEKUW9ginyd0zc3aSAkd98r5u1+tOTmU0KeIr3yc0P+tKxgB\n" + + "bAQaKrXMlLwSHHHutEkJH2KtwKx8w66VtpYtkggfTic1ae6EoVV5LpLHIlZmRMdg\n" + + "CDUatEdRweCdtO0TTR7ik8wMzs6GxAVDfTMaQ41Ks8OBnmLDZQTdRfssm2u6jYut\n" + + "DQxdF5LWe8RVlkEHB2KZJg2fWZ8bjEWr3DkCvnxRlK4Tabo5/mlymjVxTRxxRoGR\n" + + "TXU09TZASjVPzxKIyZbhgNqQvkZl2/hSCE8=\n" + + "-----END CERTIFICATE REQUEST-----"; + + private CACertificate ca; + + @BeforeEach + void setup() { + ca = new CACertificate(); + } + + @Test + void testConstructor() { + assertNull(ca.getPublicKey()); + assertNull(ca.getCertificate()); + assertEquals(1, ca.getSerial()); + assertEquals(0, ca.getSigned().size()); + assertEquals(0, ca.getRevoked().size()); + } + + @Test + void testGenerateKey() throws Throwable { + ca.generateKey(); + assertNotNull(ca.getPublicKey()); + } + + @Test + void testInstallCertificate() throws Throwable { + ca.generateKey(); + ca.installCertificate(new Certificate(new BytesReader(TestConstants.CERT_L2_RSA), false)); + assertNotNull(ca.getCertificate()); + } + + @Test + void testSignCSR() throws Throwable { + ca.generateKey(); + CertificationRequest req = ca.signCSR(); + assertArrayEquals(ObjectIdentifier.OID_SHA256_WITH_RSA_ENCRYPTION, + req.getSignatureAlgorithm().getType().getInts()); + assertEquals("CN=JCA", req.getCertificationRequestInfo().getSubject().toString()); + assertArrayEquals(ObjectIdentifier.OID_RSA_ENCRYPTION, req.getCertificationRequestInfo().getSubjectPKInfo() + .getAlgorithm().getType().getInts()); + } + + @Test + void testGetCAPublicKeyInfo() throws Throwable { + ca.generateKey(); + ca.installCertificate(new Certificate(new BytesReader(Utils.parsePEM( + Utils.byteToByte(CA.getBytes(StandardCharsets.UTF_8)), "CERTIFICATE")), false)); + assertArrayEquals(ObjectIdentifier.OID_RSA_ENCRYPTION, + ca.getCAPublicKeyInfo().getAlgorithm().getType().getInts()); + } + + @Test + void testSignCert() throws Throwable { + ca.generateKey(); + ca.installCertificate(new Certificate(new BytesReader(Utils.parsePEM( + Utils.byteToByte(CA.getBytes(StandardCharsets.UTF_8)), "CERTIFICATE")), false)); + CertificationRequestInfo req = new CertificationRequest(new BytesReader(Utils.parsePEM( + Utils.byteToByte(CSR.getBytes(StandardCharsets.UTF_8)), "CERTIFICATE REQUEST")), + false).getCertificationRequestInfo(); + Template template = new Template("123", true, null, 60); + Certificate cert = ca.signCert(req, template); + assertEquals(req.getSubject().toString(), cert.getCertificate().getSubject().toString()); + assertEquals(60, + cert.getCertificate().getValidity().getNotAfter().getTimestamp().getDayOfYear() + - cert.getCertificate().getValidity().getNotBefore().getTimestamp().getDayOfYear()); + assertEquals(1, ca.getSigned().size()); + + template = new Template("123", true, null, 60); + template.setSubject("Test Test"); + cert = ca.signCert(req, template); + assertEquals(60, + cert.getCertificate().getValidity().getNotAfter().getTimestamp().getDayOfYear() + - cert.getCertificate().getValidity().getNotBefore().getTimestamp().getDayOfYear()); + assertEquals(template.getSubject().toString(), cert.getCertificate().getSubject().toString()); + assertEquals(2, ca.getSigned().size()); + } + + @Test + void testRevoke() throws Throwable { + ca.generateKey(); + ca.installCertificate(new Certificate(new BytesReader(Utils.parsePEM( + Utils.byteToByte(CA.getBytes(StandardCharsets.UTF_8)), "CERTIFICATE")), false)); + CertificationRequestInfo req = new CertificationRequest(new BytesReader(Utils.parsePEM( + Utils.byteToByte(CSR.getBytes(StandardCharsets.UTF_8)), "CERTIFICATE REQUEST")), + false).getCertificationRequestInfo(); + Template template = new Template("123", true, null, 60); + Certificate cert = ca.signCert(req, template); + ca.revoke(new RevokedCertificate(ASN1Object.TAG_SEQUENCE, null, + cert.getCertificate().getSerialNumber(), + new UtcTime(UtcTime.TAG, null, ZonedDateTime.now(ZoneId.of("UTC"))), + Reason.KEY_COMPROMISE)); + assertEquals(1, ca.getRevoked().size()); + } + + @Test + void testSignCRL() throws Throwable { + ca.generateKey(); + ca.installCertificate(new Certificate(new BytesReader(Utils.parsePEM( + Utils.byteToByte(CA.getBytes(StandardCharsets.UTF_8)), "CERTIFICATE")), false)); + CertificationRequestInfo req = new CertificationRequest(new BytesReader(Utils.parsePEM( + Utils.byteToByte(CSR.getBytes(StandardCharsets.UTF_8)), "CERTIFICATE REQUEST")), + false).getCertificationRequestInfo(); + Template template = new Template("123", true, null, 60); + Certificate cert = ca.signCert(req, template); + ca.revoke(new RevokedCertificate(ASN1Object.TAG_SEQUENCE, null, + cert.getCertificate().getSerialNumber(), + new UtcTime(UtcTime.TAG, null, ZonedDateTime.now(ZoneId.of("UTC"))), + Reason.KEY_COMPROMISE)); + assertEquals(1, ca.signCRL().getCrl().getRevokedCertificates().length); + } +} diff --git a/src/test/model/ca/TemplateTest.java b/src/test/model/ca/TemplateTest.java new file mode 100644 index 0000000..0ca7434 --- /dev/null +++ b/src/test/model/ca/TemplateTest.java @@ -0,0 +1,27 @@ +package model.ca; + +import model.asn1.exceptions.ParseException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class TemplateTest { + @Test + void testConstructor() { + Template template = new Template("123", true, null, 123); + assertEquals("123", template.getName()); + assertTrue(template.isEnabled()); + assertNull(template.getSubject()); + assertEquals(123, template.getValidity()); + } + + @Test + void testSetSubject() throws ParseException { + Template template = new Template("123", true, null, 123); + template.setSubject("123"); + assertEquals("CN=123,C=CA", template.getSubject().toString()); + template.setSubject((String) null); + assertNull(template.getSubject()); + assertThrows(ParseException.class, () -> template.setSubject("*")); + } +} diff --git a/src/test/model/pki/cert/TbsCertificateTest.java b/src/test/model/pki/cert/TbsCertificateTest.java index ae92ace..be26eb9 100644 --- a/src/test/model/pki/cert/TbsCertificateTest.java +++ b/src/test/model/pki/cert/TbsCertificateTest.java @@ -34,6 +34,18 @@ public class TbsCertificateTest { TestConstants.CERT_GENERATED.getExtensions().getExtensions()[1].getExtnId().getInts()); } + @Test + void testGetExtension() throws ParseException { + TbsCertificate parsed = new TbsCertificate(new BytesReader(trimToTbs(TestConstants.CERT_L1_ECC)), + false); + assertNull(parsed.getExtension(ObjectIdentifier.OID_EXTENSION_REQUEST)); + assertNotNull(parsed.getExtension(ObjectIdentifier.OID_BASIC_CONSTRAINTS)); + parsed = new TbsCertificate(new BytesReader(trimToTbs(TestConstants.CERT_V1)), + false); + assertNull(parsed.getExtension(ObjectIdentifier.OID_EXTENSION_REQUEST)); + assertNull(parsed.getExtension(ObjectIdentifier.OID_BASIC_CONSTRAINTS)); + } + @Test void testParse() throws ParseException { TbsCertificate parsed = new TbsCertificate(new BytesReader(trimToTbs(TestConstants.CERT_L1_ECC)), -- cgit v1.2.3