aboutsummaryrefslogtreecommitdiff
path: root/src/test/model/pki
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/model/pki')
-rw-r--r--src/test/model/pki/AlgorithmIdentifierTest.java84
-rw-r--r--src/test/model/pki/SubjectPublicKeyInfoTest.java115
-rw-r--r--src/test/model/pki/cert/CertificateTest.java81
-rw-r--r--src/test/model/pki/cert/ExtensionTest.java118
-rw-r--r--src/test/model/pki/cert/ExtensionsTest.java112
-rw-r--r--src/test/model/pki/cert/TbsCertificateTest.java184
-rw-r--r--src/test/model/pki/cert/ValidityTest.java118
-rw-r--r--src/test/model/pki/crl/CertificateListContentTest.java37
-rw-r--r--src/test/model/pki/crl/CertificateListTest.java52
-rw-r--r--src/test/model/pki/crl/RevokedCertificateTest.java25
10 files changed, 926 insertions, 0 deletions
diff --git a/src/test/model/pki/AlgorithmIdentifierTest.java b/src/test/model/pki/AlgorithmIdentifierTest.java
new file mode 100644
index 0000000..8bcc80e
--- /dev/null
+++ b/src/test/model/pki/AlgorithmIdentifierTest.java
@@ -0,0 +1,84 @@
+package model.pki;
+
+import model.asn1.ASN1Object;
+import model.asn1.Null;
+import model.asn1.ObjectIdentifier;
+import model.asn1.exceptions.ParseException;
+import model.asn1.parsing.BytesReader;
+import org.junit.jupiter.api.Test;
+
+import static model.asn1.ObjectIdentifier.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class AlgorithmIdentifierTest {
+ @Test
+ void testConstructor() {
+ assertArrayEquals(OID_SHA256_WITH_RSA_ENCRYPTION,
+ new AlgorithmIdentifier(
+ ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, OID_SHA256_WITH_RSA_ENCRYPTION),
+ new Null(Null.TAG, null))
+ .getType().getInts());
+ assertEquals(Null.TAG.getNumber(),
+ new AlgorithmIdentifier(
+ ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, OID_SHA256_WITH_RSA_ENCRYPTION),
+ new Null(Null.TAG, null))
+ .getParameters().getTag().getNumber());
+ }
+
+ @Test
+ void testParse() throws ParseException {
+ AlgorithmIdentifier parsed = new AlgorithmIdentifier(new BytesReader(new Byte[]{
+ 0x30, 0x0d, // SEQUENCE AlgorithmIdentifier
+ 0x06, 0x09, 0x2a, -122, 0x48, -122, -9, 0x0d, // OID (rsaEncryption)
+ 0x01, 0x01, 0x01,
+ 0x05, 0x00, // Null (Parameter)
+ }), false);
+ assertArrayEquals(OID_RSA_ENCRYPTION, parsed.getType().getInts());
+ assertEquals(Null.TAG.getNumber(), parsed.getParameters().getTag().getNumber());
+
+ parsed = new AlgorithmIdentifier(new BytesReader(new Byte[]{
+ 0x30, 0x0D, // SEQUENCE AlgorithmIdentifier
+ 0x06, 0x09, 0x2A, -122, 0x48, -122, -9, 0x0D, // OID (sha256WithRsaEncryption)
+ 0x01, 0x01, 0x0B,
+ 0x05, 0x00 // Null (Parameter)
+ }), false);
+ assertArrayEquals(OID_SHA256_WITH_RSA_ENCRYPTION, parsed.getType().getInts());
+ assertEquals(Null.TAG.getNumber(), parsed.getParameters().getTag().getNumber());
+
+ parsed = new AlgorithmIdentifier(new BytesReader(new Byte[]{
+ 0x30, 0x0A, // SEQUENCE AlgorithmIdentifier
+ 0x06, 0x08, 0x2A, -122, 0x48, -50, 0x3D, 0x04, 0x03, 0x02 // OID (ecdsaWithSHA256)
+ }), false);
+ assertArrayEquals(OID_ECDSA_WITH_SHA256, parsed.getType().getInts());
+ assertNull(parsed.getParameters());
+ }
+
+ @Test
+ void testParseFail() {
+ // No type
+ assertThrows(ParseException.class, () -> new AlgorithmIdentifier(new BytesReader(new Byte[]{
+ 0x30, 0x0
+ }), false));
+ // Incorrect type tag (should be OID)
+ assertThrows(ParseException.class, () -> new AlgorithmIdentifier(new BytesReader(new Byte[]{
+ 0x30, 0x0B, // SEQUENCE AlgorithmIdentifier
+ 0x07, 0x09, 0x2A, -122, 0x48, -122, -9, 0x0D, // Incorrect tag
+ 0x01, 0x01, 0x0B,
+ }), false));
+ }
+
+ @Test
+ void testEncode() throws ParseException {
+ assertArrayEquals(new Byte[]{
+ 0x30, 0x0D, // SEQUENCE AlgorithmIdentifier
+ 0x06, 0x09, 0x2A, -122, 0x48, -122, -9, 0x0D, // OID (sha256WithRsaEncryption)
+ 0x01, 0x01, 0x0B,
+ 0x05, 0x00 // Null (Parameter)
+ }, new AlgorithmIdentifier(
+ ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, OID_SHA256_WITH_RSA_ENCRYPTION),
+ new Null(Null.TAG, null)).encodeDER());
+ }
+}
diff --git a/src/test/model/pki/SubjectPublicKeyInfoTest.java b/src/test/model/pki/SubjectPublicKeyInfoTest.java
new file mode 100644
index 0000000..f1cfff0
--- /dev/null
+++ b/src/test/model/pki/SubjectPublicKeyInfoTest.java
@@ -0,0 +1,115 @@
+package model.pki;
+
+import model.asn1.ASN1Object;
+import model.asn1.BitString;
+import model.asn1.Null;
+import model.asn1.ObjectIdentifier;
+import model.asn1.exceptions.ParseException;
+import model.asn1.parsing.BytesReader;
+import model.csr.CertificationRequestInfo;
+import model.csr.CertificationRequestInfoTest;
+import org.junit.jupiter.api.Test;
+
+import static model.TestConstants.mutate;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class SubjectPublicKeyInfoTest {
+ private static final Byte[] RSA = new Byte[] {
+ 0x30, -127, -97, // SEQUENCE SubjectPublicKeyInfo
+ 0x30, 0x0d, // SEQUENCE AlgorithmIdentifier
+ 0x06, 0x09, 0x2a, -122, 0x48, -122, -9, 0x0d, // OID (rsaEncryption)
+ 0x01, 0x01, 0x01,
+ 0x05, 0x00, // Null (Parameter)
+ 0x03, -127, -115, 0x00, 0x30, -127, -119, 0x02, // BIT STRING (subjectPublicKey)
+ -127, -127, 0x00, -67, -1, 0x4e, 0x6d, -22,
+ 0x62, 0x6a, 0x11, -120, 0x77, 0x0a, -92, 0x32,
+ -124, -37, 0x22, 0x2f, 0x3d, 0x5d, 0x2a, 0x63,
+ -71, -109, 0x11, -50, -92, 0x4f, -119, 0x3b,
+ 0x14, 0x3b, -54, 0x3c, -106, -42, 0x11, 0x42,
+ 0x78, -110, 0x68, -100, -25, -25, -50, 0x75,
+ -101, 0x21, 0x41, -34, -31, -85, -13, 0x1e,
+ 0x51, -81, 0x25, 0x4f, -1, 0x56, 0x77, 0x5e,
+ -30, 0x27, -104, 0x34, 0x67, -28, -56, 0x55,
+ 0x6a, 0x3c, 0x6f, -38, -85, -63, 0x5f, 0x16,
+ 0x7a, -93, -19, -35, 0x7f, 0x35, 0x0f, -47,
+ -7, -22, -12, -24, -48, 0x25, 0x6d, -114,
+ 0x66, 0x1a, 0x53, -77, 0x67, 0x32, -69, -39,
+ 0x57, -42, -65, -13, 0x5f, 0x6f, 0x53, 0x6d,
+ 0x62, -95, 0x42, 0x12, 0x7b, 0x13, 0x4f, 0x1a,
+ -26, 0x00, -72, -32, 0x2b, -83, 0x3c, 0x35,
+ -103, 0x18, 0x51, 0x02, 0x03, 0x01, 0x00, 0x01,
+ };
+
+ private static final Byte[] ECC = new Byte[] {
+ 0x30, 0x59, // SEQUENCE SubjectPublicKeyInfo
+ 0x30, 0x13, // SEQUENCE AlgorithmIdentifier
+ 0x06, 0x07, 0x2A, -122, 0x48, -50, 0x3D, 0x02, 0x01, // OID (ecPublicKey)
+ 0x06, 0x08, 0x2A, -122, 0x48, -50, 0x3D, 0x03, 0x01, // OID Parameter (prime256v1)
+ 0x07,
+ 0x03, 0x42, // BIT STRING
+ 0x00, 0x04, 0x1D, -24, 0x71, -68, -35, 0x48, 0x70,
+ 0x26, 0x71, 0x6C, -35, 0x04, 0x5B, 0x3F, 0x5D, -34,
+ 0x14, 0x31, -117, 0x3F, 0x31, -128, 0x18, 0x2A, 0x33,
+ -27, 0x19, -122, 0x13, -42, -25, 0x48, 0x2F, -107,
+ 0x15, 0x3A, 0x59, -115, -19, 0x09, -28, 0x53, 0x1A,
+ -13, 0x61, -78, 0x35, 0x61, 0x6E, 0x66, 0x5F, 0x5F,
+ -49, 0x0A, -30, 0x65, 0x65, 0x3D, 0x22, 0x2B, 0x30,
+ 0x71, 0x2C, 0x24
+ };
+
+ @Test
+ void testConstructor() {
+ assertArrayEquals(ObjectIdentifier.OID_SHA256_WITH_RSA_ENCRYPTION,
+ new SubjectPublicKeyInfo(ASN1Object.TAG_SEQUENCE, null,
+ new AlgorithmIdentifier(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null,
+ ObjectIdentifier.OID_SHA256_WITH_RSA_ENCRYPTION),
+ new Null(Null.TAG, null)),
+ new BitString(BitString.TAG, null,
+ 0, new Byte[]{ 1, 2, 3}))
+ .getAlgorithm().getType().getInts());
+ assertArrayEquals(new Byte[]{ 1, 2, 3 },
+ new SubjectPublicKeyInfo(ASN1Object.TAG_SEQUENCE, null,
+ new AlgorithmIdentifier(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null,
+ ObjectIdentifier.OID_SHA256_WITH_RSA_ENCRYPTION),
+ new Null(Null.TAG, null)),
+ new BitString(BitString.TAG, null,
+ 0, new Byte[]{ 1, 2, 3}))
+ .getSubjectPublicKey().getConvertedVal());
+ }
+
+ @Test
+ void testParse() throws ParseException {
+ SubjectPublicKeyInfo parsed = new SubjectPublicKeyInfo(new BytesReader(RSA), false);
+ assertArrayEquals(ObjectIdentifier.OID_RSA_ENCRYPTION, parsed.getAlgorithm().getType().getInts());
+ assertEquals(Null.TAG.getNumber(), parsed.getAlgorithm().getParameters().getTag().getNumber());
+ assertEquals(140, parsed.getSubjectPublicKey().getConvertedVal().length);
+
+ parsed = new SubjectPublicKeyInfo(new BytesReader(ECC), false);
+ assertArrayEquals(ObjectIdentifier.OID_EC_PUBLIC_KEY, parsed.getAlgorithm().getType().getInts());
+ assertEquals(ObjectIdentifier.TAG.getNumber(), parsed.getAlgorithm().getParameters().getTag().getNumber());
+ assertArrayEquals(ObjectIdentifier.OID_PRIME256_V1,
+ ((ObjectIdentifier) parsed.getAlgorithm().getParameters()).getInts());
+ assertEquals(65, parsed.getSubjectPublicKey().getConvertedVal().length);
+ }
+
+ @Test
+ void testParseFail() {
+ // No algorithm
+ assertThrows(ParseException.class, () -> {
+ new SubjectPublicKeyInfo(new BytesReader(new Byte[]{
+ 0x30, 0
+ }), false);
+ });
+ // Incorrect algorithm ID tag
+ assertThrows(ParseException.class, () -> {
+ new CertificationRequestInfo(new BytesReader(mutate(RSA, 3, 0x30, 0x31)), false);
+ });
+ // Incorrect public key tag
+ assertThrows(ParseException.class, () -> {
+ new CertificationRequestInfo(new BytesReader(mutate(RSA, 18, BitString.TAG.getNumber(), 0x31)),
+ false);
+ });
+ }
+}
diff --git a/src/test/model/pki/cert/CertificateTest.java b/src/test/model/pki/cert/CertificateTest.java
new file mode 100644
index 0000000..70564fc
--- /dev/null
+++ b/src/test/model/pki/cert/CertificateTest.java
@@ -0,0 +1,81 @@
+package model.pki.cert;
+
+import model.TestConstants;
+import model.asn1.*;
+import model.asn1.exceptions.ParseException;
+import model.asn1.parsing.BytesReader;
+import model.csr.CertificationRequest;
+import model.csr.CertificationRequestInfo;
+import model.csr.CertificationRequestInfoTest;
+import model.pki.AlgorithmIdentifier;
+import model.pki.SubjectPublicKeyInfo;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Stream;
+
+import static model.TestConstants.mutate;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class CertificateTest {
+ @Test
+ void testConstructor() {
+ final Certificate certificate = new Certificate(ASN1Object.TAG_SEQUENCE, null,
+ TestConstants.CERT_GENERATED,
+ new AlgorithmIdentifier(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_RSA_ENCRYPTION),
+ new Null(Null.TAG, null)),
+ new BitString(BitString.TAG, null, 0, new Byte[]{ 1, 2, 3 }));
+
+ assertEquals(TbsCertificate.VERSION_V3,
+ certificate.getCertificate().getVersion().getLong());
+ assertArrayEquals(ObjectIdentifier.OID_RSA_ENCRYPTION,
+ certificate.getSignatureAlgorithm().getType().getInts());
+ assertArrayEquals(new Byte[]{ 1, 2, 3 },
+ certificate.getSignature().getConvertedVal());
+ }
+
+ @Test
+ void testParse() throws ParseException {
+ Certificate parsed = new Certificate(new BytesReader(TestConstants.CERT_L2_RSA), false);
+ assertEquals(TbsCertificate.VERSION_V3,
+ parsed.getCertificate().getVersion().getLong());
+ assertArrayEquals(ObjectIdentifier.OID_ECDSA_WITH_SHA512, parsed.getSignatureAlgorithm().getType().getInts());
+ assertNull(parsed.getSignatureAlgorithm().getParameters());
+ assertEquals(70, parsed.getSignature().getVal().length);
+
+ parsed = new Certificate(new BytesReader(TestConstants.CERT_L1_ECC), false);
+ assertEquals(TbsCertificate.VERSION_V3,
+ parsed.getCertificate().getVersion().getLong());
+ assertArrayEquals(ObjectIdentifier.OID_ECDSA_WITH_SHA256, parsed.getSignatureAlgorithm().getType().getInts());
+ assertNull(parsed.getSignatureAlgorithm().getParameters());
+ assertEquals(71, parsed.getSignature().getVal().length);
+ }
+
+ @Test
+ void testParseFail() {
+ // Incorrect certificate tag
+ assertThrows(ParseException.class, () ->
+ new Certificate(new BytesReader(mutate(TestConstants.CERT_L1_ECC, 4, 0x30, 0x31)), false)
+ );
+ // Incorrect signatureAlgorithm tag
+ assertThrows(ParseException.class, () ->
+ new Certificate(new BytesReader(mutate(TestConstants.CERT_L1_ECC, 349, 0x30, 0x31)), false)
+ );
+ // Incorrect signature tag
+ assertThrows(ParseException.class, () ->
+ new Certificate(new BytesReader(mutate(TestConstants.CERT_L1_ECC, 361, 0x3, 0x5)), false)
+ );
+ }
+
+ @Test
+ void testEncode() throws ParseException {
+ assertArrayEquals(TestConstants.CERT_V1,
+ new Certificate(new BytesReader(TestConstants.CERT_V1), false).encodeDER());
+ assertArrayEquals(TestConstants.CERT_L1_ECC,
+ new Certificate(new BytesReader(TestConstants.CERT_L1_ECC), false).encodeDER());
+ assertArrayEquals(TestConstants.CERT_L2_RSA,
+ new Certificate(new BytesReader(TestConstants.CERT_L2_RSA), false).encodeDER());
+ }
+}
diff --git a/src/test/model/pki/cert/ExtensionTest.java b/src/test/model/pki/cert/ExtensionTest.java
new file mode 100644
index 0000000..06561ba
--- /dev/null
+++ b/src/test/model/pki/cert/ExtensionTest.java
@@ -0,0 +1,118 @@
+package model.pki.cert;
+
+import model.asn1.ASN1Object;
+import model.asn1.Bool;
+import model.asn1.ObjectIdentifier;
+import model.asn1.OctetString;
+import model.asn1.exceptions.ParseException;
+import model.asn1.parsing.BytesReader;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class ExtensionTest {
+ static final Byte[] EXT_SUBJECT_KEY_ID = new Byte[] {
+ 0x30, 0x1D, // SEQUENCE Extension
+ 0x06, 0x03, 0x55, 0x1D, 0x0E, // OID subjectKeyIdentifier
+ 0x04, 0x16, // OCTET STRING
+ 0x04, 0x14, -79, -62, -89, -127, 0x63, 0x66,
+ 0x4B, 0x72, 0x0A, -35, -3, 0x7D, 0x20, 0x29,
+ -67, 0x6B, 0x49, 0x09, 0x61, -64
+ };
+
+ static final Byte[] EXT_KEY_USAGE = new Byte[] {
+ 0x30, 0x0E, // SEQUENCE Extension
+ 0x06, 0x03, 0x55, 0x1D, 0x0F, // OID keyUsage
+ 0x01, 0x01, -1, // BOOLEAN critical
+ 0x04, 0x04, // OCTET STRING
+ 0x03, 0x02, 0x01, -122
+ };
+
+ @Test
+ void testConstructor() throws ParseException {
+ final Extension ext = new Extension(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_BASIC_CONSTRAINTS),
+ new Bool(Bool.TAG, null, true),
+ new OctetString(OctetString.TAG, null, new Byte[]{ 0x30, 0x03, 0x01, 0x01, -1 }));
+ assertArrayEquals(ObjectIdentifier.OID_BASIC_CONSTRAINTS, ext.getExtnId().getInts());
+ assertTrue(ext.getCritical().getValue());
+ assertArrayEquals(new Byte[]{ 0x30, 0x03, 0x01, 0x01, -1 }, ext.getExtnValue().getBytes());
+ }
+
+ @Test
+ void testParse() throws ParseException {
+ Extension parsed = new Extension(new BytesReader(EXT_SUBJECT_KEY_ID), false);
+ assertArrayEquals(ObjectIdentifier.OID_SUBJECT_KEY_IDENTIFIER, parsed.getExtnId().getInts());
+ assertNull(parsed.getCritical());
+ assertArrayEquals(new Byte[] {
+ 0x04, 0x14, -79, -62, -89, -127, 0x63, 0x66,
+ 0x4B, 0x72, 0x0A, -35, -3, 0x7D, 0x20, 0x29,
+ -67, 0x6B, 0x49, 0x09, 0x61, -64
+ }, parsed.getExtnValue().getBytes());
+
+ parsed = new Extension(new BytesReader(EXT_KEY_USAGE), false);
+ assertArrayEquals(ObjectIdentifier.OID_KEY_USAGE, parsed.getExtnId().getInts());
+ assertTrue(parsed.getCritical().getValue());
+ assertArrayEquals(new Byte[] {
+ 0x03, 0x02, 0x01, -122
+ }, parsed.getExtnValue().getBytes());
+ }
+
+ @Test
+ void testParseFail() throws ParseException {
+ // Too short (no ID)
+ assertThrows(ParseException.class, () -> new Extension(new BytesReader(new Byte[]{
+ 0x30, 0x00
+ }), false));
+ // Wrong ID tag
+ assertThrows(ParseException.class, () -> new Extension(new BytesReader(new Byte[]{
+ 0x30, 0x0E, // SEQUENCE Extension
+ 0x07, 0x03, 0x55, 0x1D, 0x0F, // OID keyUsage
+ 0x01, 0x01, -1, // BOOLEAN critical
+ 0x04, 0x04, // OCTET STRING
+ 0x03, 0x02, 0x01, -122
+ }), false));
+ // Wrong critical tag (neither bool nor sequence)
+ assertThrows(ParseException.class, () -> new Extension(new BytesReader(new Byte[]{
+ 0x30, 0x0E, // SEQUENCE Extension
+ 0x06, 0x03, 0x55, 0x1D, 0x0F, // OID keyUsage
+ 0x05, 0x01, -1, // BOOLEAN critical
+ 0x04, 0x04, // OCTET STRING
+ 0x03, 0x02, 0x01, -122
+ }), false));
+ // Critical and wrong value tag
+ assertThrows(ParseException.class, () -> new Extension(new BytesReader(new Byte[]{
+ 0x30, 0x0E, // SEQUENCE Extension
+ 0x06, 0x03, 0x55, 0x1D, 0x0F, // OID keyUsage
+ 0x01, 0x01, -1, // BOOLEAN critical
+ 0x09, 0x04, // OCTET STRING
+ 0x03, 0x02, 0x01, -122
+ }), false));
+
+ // No critical and wrong value tag
+ assertThrows(ParseException.class, () -> new Extension(new BytesReader(new Byte[]{
+ 0x30, 0x0B, // SEQUENCE Extension
+ 0x06, 0x03, 0x55, 0x1D, 0x0F, // OID keyUsage
+ 0x09, 0x04, // OCTET STRING
+ 0x03, 0x02, 0x01, -122
+ }), false));
+ }
+
+ @Test
+ void testEncode() {
+ assertArrayEquals(EXT_SUBJECT_KEY_ID, new Extension(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_SUBJECT_KEY_IDENTIFIER),
+ null,
+ new OctetString(OctetString.TAG, null, new Byte[] {
+ 0x04, 0x14, -79, -62, -89, -127, 0x63, 0x66,
+ 0x4B, 0x72, 0x0A, -35, -3, 0x7D, 0x20, 0x29,
+ -67, 0x6B, 0x49, 0x09, 0x61, -64
+ })).encodeDER());
+ assertArrayEquals(EXT_KEY_USAGE, new Extension(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_KEY_USAGE),
+ new Bool(Bool.TAG, null, true),
+ new OctetString(OctetString.TAG, null, new Byte[] {
+ 0x03, 0x02, 0x01, -122
+ })).encodeDER());
+ }
+}
diff --git a/src/test/model/pki/cert/ExtensionsTest.java b/src/test/model/pki/cert/ExtensionsTest.java
new file mode 100644
index 0000000..e50b3e6
--- /dev/null
+++ b/src/test/model/pki/cert/ExtensionsTest.java
@@ -0,0 +1,112 @@
+package model.pki.cert;
+
+import model.asn1.ASN1Object;
+import model.asn1.Bool;
+import model.asn1.ObjectIdentifier;
+import model.asn1.OctetString;
+import model.asn1.exceptions.ParseException;
+import model.asn1.parsing.BytesReader;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class ExtensionsTest {
+ @Test
+ void testConstructor() {
+ final Extension ext1 = new Extension(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_BASIC_CONSTRAINTS),
+ new Bool(Bool.TAG, null, true),
+ new OctetString(OctetString.TAG, null, new Byte[]{0x30, 0x03, 0x01, 0x01, -1}));
+ final Extension ext2 = new Extension(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_SUBJECT_KEY_IDENTIFIER),
+ null,
+ new OctetString(OctetString.TAG, null, new Byte[]{
+ 0x04, 0x14, -79, -62, -89, -127, 0x63, 0x66,
+ 0x4B, 0x72, 0x0A, -35, -3, 0x7D, 0x20, 0x29,
+ -67, 0x6B, 0x49, 0x09, 0x61, -64
+ }));
+ final Extensions extensions = new Extensions(ASN1Object.TAG_SEQUENCE, null, new Extension[]{
+ ext1, ext2
+ });
+
+ assertEquals(2, extensions.getExtensions().length);
+ assertArrayEquals(ObjectIdentifier.OID_BASIC_CONSTRAINTS, extensions.getExtensions()[0].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_SUBJECT_KEY_IDENTIFIER, extensions.getExtensions()[1].getExtnId().getInts());
+ }
+
+ @Test
+ void testParse() throws ParseException {
+ final Extensions parsed = new Extensions(new BytesReader(
+ Stream.of(Arrays.asList(new Byte[]{0x30,
+ (byte) (ExtensionTest.EXT_KEY_USAGE.length + ExtensionTest.EXT_SUBJECT_KEY_ID.length)}),
+ Arrays.asList(ExtensionTest.EXT_KEY_USAGE),
+ Arrays.asList(ExtensionTest.EXT_SUBJECT_KEY_ID))
+ .flatMap(Collection::stream)
+ .toArray(Byte[]::new)), false);
+ assertArrayEquals(ObjectIdentifier.OID_KEY_USAGE, parsed.getExtensions()[0].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_SUBJECT_KEY_IDENTIFIER, parsed.getExtensions()[1].getExtnId().getInts());
+ }
+
+ @Test
+ void testParseFail() {
+ assertThrows(ParseException.class, () -> {
+ new Extensions(new BytesReader(new Byte[]{0x30, 0x1}), false);
+ });
+ assertThrows(ParseException.class, () -> {
+ Byte[] bytes =
+ Stream.of(Arrays.asList(new Byte[]{0x30,
+ (byte) (ExtensionTest.EXT_KEY_USAGE.length + ExtensionTest.EXT_SUBJECT_KEY_ID.length)}),
+ Arrays.asList(ExtensionTest.EXT_KEY_USAGE),
+ Arrays.asList(ExtensionTest.EXT_SUBJECT_KEY_ID))
+ .flatMap(Collection::stream)
+ .toArray(Byte[]::new);
+ assertEquals((byte) 0x30, bytes[2]);
+ bytes[2] = 0x31;
+ new Extensions(new BytesReader(bytes), false);
+ });
+ assertThrows(ParseException.class, () -> {
+ Byte[] bytes =
+ Stream.of(Arrays.asList(new Byte[]{0x30,
+ (byte) (ExtensionTest.EXT_KEY_USAGE.length + ExtensionTest.EXT_SUBJECT_KEY_ID.length)}),
+ Arrays.asList(ExtensionTest.EXT_KEY_USAGE),
+ Arrays.asList(ExtensionTest.EXT_SUBJECT_KEY_ID))
+ .flatMap(Collection::stream)
+ .toArray(Byte[]::new);
+ assertEquals((byte) 0x30, bytes[2 + ExtensionTest.EXT_KEY_USAGE.length]);
+ bytes[2 + ExtensionTest.EXT_KEY_USAGE.length] = 0x31;
+ new Extensions(new BytesReader(bytes), false);
+ });
+ }
+
+ @Test
+ void testEncode() {
+ assertArrayEquals(
+ Stream.of(Arrays.asList(new Byte[]{0x30,
+ (byte) (ExtensionTest.EXT_KEY_USAGE.length +
+ ExtensionTest.EXT_SUBJECT_KEY_ID.length)}),
+ Arrays.asList(ExtensionTest.EXT_SUBJECT_KEY_ID),
+ Arrays.asList(ExtensionTest.EXT_KEY_USAGE))
+ .flatMap(Collection::stream)
+ .toArray(Byte[]::new),
+ new Extensions(ASN1Object.TAG_SEQUENCE, null, new Extension[]{
+ new Extension(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_SUBJECT_KEY_IDENTIFIER),
+ null,
+ new OctetString(OctetString.TAG, null, new Byte[]{
+ 0x04, 0x14, -79, -62, -89, -127, 0x63, 0x66,
+ 0x4B, 0x72, 0x0A, -35, -3, 0x7D, 0x20, 0x29,
+ -67, 0x6B, 0x49, 0x09, 0x61, -64
+ })),
+ new Extension(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_KEY_USAGE),
+ new Bool(Bool.TAG, null, true),
+ new OctetString(OctetString.TAG, null, new Byte[]{
+ 0x03, 0x02, 0x01, -122
+ }))
+ }).encodeDER());
+ }
+}
diff --git a/src/test/model/pki/cert/TbsCertificateTest.java b/src/test/model/pki/cert/TbsCertificateTest.java
new file mode 100644
index 0000000..ae92ace
--- /dev/null
+++ b/src/test/model/pki/cert/TbsCertificateTest.java
@@ -0,0 +1,184 @@
+package model.pki.cert;
+
+import model.asn1.*;
+import model.asn1.exceptions.ParseException;
+import model.asn1.parsing.BytesReader;
+import model.TestConstants;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigInteger;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Arrays;
+
+import static model.TestConstants.mutate;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class TbsCertificateTest {
+ @Test
+ void testConstructor() {
+ assertEquals(TbsCertificate.VERSION_V3, TestConstants.CERT_GENERATED.getVersion().getLong());
+ assertEquals(100, TestConstants.CERT_GENERATED.getSerialNumber().getLong());
+ assertArrayEquals(ObjectIdentifier.OID_RSA_ENCRYPTION, TestConstants.CERT_GENERATED.getSignature().getType().getInts());
+ assertEquals("CN=Test CA,C=CA", TestConstants.CERT_GENERATED.getIssuer().toString());
+ assertEquals(TestConstants.NOW, TestConstants.CERT_GENERATED.getValidity().getNotBefore().getTimestamp());
+ assertEquals(TestConstants.NOW.plusYears(1),
+ TestConstants.CERT_GENERATED.getValidity().getNotAfter().getTimestamp());
+ assertEquals("CN=Yuuta Liang,C=CA", TestConstants.CERT_GENERATED.getSubject().toString());
+ assertArrayEquals(ObjectIdentifier.OID_EC_PUBLIC_KEY,
+ TestConstants.CERT_GENERATED.getSubjectPublicKeyInfo().getAlgorithm().getType().getInts());
+ assertEquals(2, TestConstants.CERT_GENERATED.getExtensions().getExtensions().length);
+ assertArrayEquals(ObjectIdentifier.OID_BASIC_CONSTRAINTS,
+ TestConstants.CERT_GENERATED.getExtensions().getExtensions()[0].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_KEY_USAGE,
+ TestConstants.CERT_GENERATED.getExtensions().getExtensions()[1].getExtnId().getInts());
+ }
+
+ @Test
+ void testParse() throws ParseException {
+ TbsCertificate parsed = new TbsCertificate(new BytesReader(trimToTbs(TestConstants.CERT_L1_ECC)),
+ false);
+ assertEquals(TbsCertificate.VERSION_V3, parsed.getVersion().getLong());
+ assertEquals(0, parsed.getSerialNumber().getValue()
+ .compareTo(new BigInteger("644983544608556543477205958886697401602227090424")));
+ assertArrayEquals(ObjectIdentifier.OID_ECDSA_WITH_SHA256,
+ parsed.getSignature().getType().getInts());
+ assertNull(parsed.getSignature().getParameters());
+ assertEquals("CN=Yuuta Root CA,C=CA", parsed.getIssuer().toString());
+ assertEquals(ZonedDateTime.of(2023, 6, 23,
+ 2, 50, 46, 0, ZoneId.of("UTC")),
+ parsed.getValidity().getNotBefore().getTimestamp());
+ assertEquals(ZonedDateTime.of(2048, 6, 23,
+ 2, 50, 46, 0, ZoneId.of("UTC")),
+ parsed.getValidity().getNotAfter().getTimestamp());
+ assertEquals("CN=Yuuta Root CA,C=CA", parsed.getSubject().toString());
+ assertArrayEquals(ObjectIdentifier.OID_EC_PUBLIC_KEY,
+ parsed.getSubjectPublicKeyInfo().getAlgorithm().getType().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_PRIME256_V1,
+ ((ObjectIdentifier) parsed.getSubjectPublicKeyInfo().getAlgorithm().getParameters()).getInts());
+ assertEquals(4, parsed.getExtensions().getExtensions().length);
+ assertArrayEquals(ObjectIdentifier.OID_SUBJECT_KEY_IDENTIFIER,
+ parsed.getExtensions().getExtensions()[0].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_AUTHORITY_KEY_IDENTIFIER,
+ parsed.getExtensions().getExtensions()[1].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_BASIC_CONSTRAINTS,
+ parsed.getExtensions().getExtensions()[2].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_KEY_USAGE,
+ parsed.getExtensions().getExtensions()[3].getExtnId().getInts());
+
+ parsed = new TbsCertificate(
+ new BytesReader(trimToTbs(TestConstants.CERT_L2_RSA)),
+ false);
+ assertEquals(TbsCertificate.VERSION_V3, parsed.getVersion().getLong());
+ assertEquals(0, parsed.getSerialNumber().getValue()
+ .compareTo(new BigInteger("354327098948136693059815576591331472151989570311")));
+ assertArrayEquals(ObjectIdentifier.OID_ECDSA_WITH_SHA512,
+ parsed.getSignature().getType().getInts());
+ assertNull(parsed.getSignature().getParameters());
+ assertEquals("CN=Yuuta Root CA,C=CA", parsed.getIssuer().toString());
+ assertEquals(ZonedDateTime.of(2023, 6, 24,
+ 0, 15, 22, 0, ZoneId.of("UTC")),
+ parsed.getValidity().getNotBefore().getTimestamp());
+ assertEquals(ZonedDateTime.of(2033, 6, 21,
+ 0, 15, 22, 0, ZoneId.of("UTC")),
+ parsed.getValidity().getNotAfter().getTimestamp());
+ assertEquals("DC=MOE,DC=YUUTA,DC=AD,CN=Yuuta Home Issuing CA", parsed.getSubject().toString());
+ assertArrayEquals(ObjectIdentifier.OID_RSA_ENCRYPTION,
+ parsed.getSubjectPublicKeyInfo().getAlgorithm().getType().getInts());
+ assertEquals(Null.TAG.getNumber(),
+ parsed.getSubjectPublicKeyInfo().getAlgorithm().getParameters().getTag().getNumber());
+ assertEquals(526, parsed.getSubjectPublicKeyInfo().getSubjectPublicKey().getVal().length);
+ assertEquals(6, parsed.getExtensions().getExtensions().length);
+ assertArrayEquals(ObjectIdentifier.OID_SUBJECT_KEY_IDENTIFIER,
+ parsed.getExtensions().getExtensions()[0].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_AUTHORITY_KEY_IDENTIFIER,
+ parsed.getExtensions().getExtensions()[1].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_BASIC_CONSTRAINTS,
+ parsed.getExtensions().getExtensions()[2].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_KEY_USAGE,
+ parsed.getExtensions().getExtensions()[3].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_CRL_DISTRIBUTION_POINTS,
+ parsed.getExtensions().getExtensions()[4].getExtnId().getInts());
+ assertArrayEquals(ObjectIdentifier.OID_AUTHORITY_INFO_ACCESS,
+ parsed.getExtensions().getExtensions()[5].getExtnId().getInts());
+
+ parsed = new TbsCertificate(
+ new BytesReader(Arrays.stream(TestConstants.CERT_V1).skip(4).toArray(Byte[]::new)),
+ false);
+ assertNull(parsed.getVersion());
+ assertNull(parsed.getExtensions());
+ }
+
+ @Test
+ void testParseFail() throws ParseException {
+ final Byte[] in = trimToTbs(TestConstants.CERT_L2_RSA);
+ // Wrong version parent tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 4, -96, 2)), false));
+ // Wrong version inner tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 6, 0x2, 3)), false));
+ // Wrong serial number tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 9, 0x2, 3)), false));
+ // Wrong signature tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 31, 0x30, 3)), false));
+ // Wrong issuer tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 43, 0x30, 0x31)), false));
+ // Wrong validity tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 82, 0x30, 0x31)), false));
+ // Wrong subject tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 114, 0x30, 0x31)), false));
+ // Wrong subject public key info tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 212, 0x30, 0x31)), false));
+ // Wrong extensions parent tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 762, -93, 0x31)), false));
+ // Wrong extensions inner tag
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 765, 0x30, 0x31)), false));
+ // Extensions exist, but wrong version
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 8, 0x2, TbsCertificate.VERSION_V2)),
+ false));
+ // Totally wrong version
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(mutate(in, 8, 0x2, TbsCertificate.VERSION_V3 + 1)),
+ false));
+
+ // Extensions exist, but no version
+ final TbsCertificate certV1 = new TbsCertificate(new BytesReader(trimToTbs(TestConstants.CERT_V1)), false);
+ final TbsCertificate certV3 = new TbsCertificate(new BytesReader(trimToTbs(TestConstants.CERT_L2_RSA)), false);
+ Byte[] wrongCert = new TbsCertificate(ASN1Object.TAG_SEQUENCE, null,
+ null,
+ certV1.getSerialNumber(),
+ certV1.getSignature(),
+ certV1.getIssuer(),
+ certV1.getValidity(),
+ certV1.getSubject(),
+ certV1.getSubjectPublicKeyInfo(),
+ certV3.getExtensions())
+ .encodeDER();
+ assertThrows(ParseException.class, () ->
+ new TbsCertificate(new BytesReader(wrongCert), false));
+ }
+
+ @Test
+ void testEncode() throws ParseException {
+ Byte[] in = trimToTbs(TestConstants.CERT_L1_ECC);
+ assertArrayEquals(Arrays.copyOfRange(in, 0, 345), new TbsCertificate(new BytesReader(in), false).encodeDER());
+ in = trimToTbs(TestConstants.CERT_L2_RSA);
+ assertArrayEquals(Arrays.copyOfRange(in, 0, 989), new TbsCertificate(new BytesReader(in), false).encodeDER());
+ in = trimToTbs(TestConstants.CERT_V1);
+ assertArrayEquals(Arrays.copyOfRange(in, 0, 583), new TbsCertificate(new BytesReader(in), false).encodeDER());
+ }
+
+ private static Byte[] trimToTbs(Byte[] in) {
+ return Arrays.stream(in).skip(4).toArray(Byte[]::new);
+ }
+}
diff --git a/src/test/model/pki/cert/ValidityTest.java b/src/test/model/pki/cert/ValidityTest.java
new file mode 100644
index 0000000..eba5092
--- /dev/null
+++ b/src/test/model/pki/cert/ValidityTest.java
@@ -0,0 +1,118 @@
+package model.pki.cert;
+
+import jdk.jshell.EvalException;
+import model.asn1.*;
+import model.asn1.exceptions.ParseException;
+import model.asn1.parsing.BytesReader;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Stream;
+
+import static model.TestConstants.combine;
+import static model.TestConstants.mutate;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class ValidityTest {
+ private ZonedDateTime now;
+
+ @BeforeEach
+ void setup() {
+ now = ZonedDateTime.now(ZoneId.of("UTC")).withNano(0);
+ }
+
+ @Test
+ void testConstructor() {
+ final ASN1Time time = new GeneralizedTime(GeneralizedTime.TAG, null, now);
+ assertEquals(time.getTimestamp(), new Validity(ASN1Object.TAG_SEQUENCE, null, time, time)
+ .getNotBefore().getTimestamp());
+ assertEquals(time.getTimestamp(), new Validity(ASN1Object.TAG_SEQUENCE, null, time, time)
+ .getNotAfter().getTimestamp());
+ }
+
+ @Test
+ void testParse() throws ParseException {
+ final ASN1Time utc = new UtcTime(UtcTime.TAG, null, now);
+ final ASN1Time gen = new GeneralizedTime(GeneralizedTime.TAG, null, now);
+ final Byte[] utcBytes = utc.encodeDER();
+ final Byte[] genBytes = gen.encodeDER();
+
+ // UTC, Generalized
+ Validity parsed = new Validity(new BytesReader(combine((byte) ASN1Object.TAG_SEQUENCE.getNumber(), utcBytes,
+ genBytes)), false);
+ assertEquals(UtcTime.TAG.getNumber(), parsed.getNotBefore().getTag().getNumber());
+ assertEquals(now, parsed.getNotBefore().getTimestamp());
+ assertEquals(GeneralizedTime.TAG.getNumber(), parsed.getNotAfter().getTag().getNumber());
+ assertEquals(now, parsed.getNotAfter().getTimestamp());
+
+ // UTC, UTC
+ parsed = new Validity(new BytesReader(combine((byte) ASN1Object.TAG_SEQUENCE.getNumber(), utcBytes, utcBytes)),
+ false);
+ assertEquals(UtcTime.TAG.getNumber(), parsed.getNotBefore().getTag().getNumber());
+ assertEquals(now, parsed.getNotBefore().getTimestamp());
+ assertEquals(UtcTime.TAG.getNumber(), parsed.getNotAfter().getTag().getNumber());
+ assertEquals(now, parsed.getNotAfter().getTimestamp());
+
+ // Generalized, Generalized
+ parsed = new Validity(new BytesReader(combine((byte) ASN1Object.TAG_SEQUENCE.getNumber(), genBytes, genBytes)),
+ false);
+ assertEquals(GeneralizedTime.TAG.getNumber(), parsed.getNotBefore().getTag().getNumber());
+ assertEquals(now, parsed.getNotBefore().getTimestamp());
+ assertEquals(GeneralizedTime.TAG.getNumber(), parsed.getNotAfter().getTag().getNumber());
+ assertEquals(now, parsed.getNotAfter().getTimestamp());
+
+ // Generalized, UTC
+ parsed = new Validity(new BytesReader(combine((byte) ASN1Object.TAG_SEQUENCE.getNumber(), genBytes, utcBytes)),
+ false);
+ assertEquals(GeneralizedTime.TAG.getNumber(), parsed.getNotBefore().getTag().getNumber());
+ assertEquals(now, parsed.getNotBefore().getTimestamp());
+ assertEquals(UtcTime.TAG.getNumber(), parsed.getNotAfter().getTag().getNumber());
+ assertEquals(now, parsed.getNotAfter().getTimestamp());
+ }
+
+ @Test
+ void testParseFail() {
+ final ASN1Time utc = new UtcTime(UtcTime.TAG, null, now);
+ final Byte[] utcBytes = utc.encodeDER();
+
+ // Too short
+ assertThrows(ParseException.class, () ->
+ new Validity(new BytesReader(new Byte[] {
+ 0x30, 0x0
+ }), false));
+ assertThrows(ParseException.class, () -> {
+ new Validity(new BytesReader(combine((byte) 0x30, utcBytes)), false);
+ });
+
+ // Illegal notBefore tag
+ assertThrows(ParseException.class, () -> {
+ new Validity(new BytesReader(mutate(combine((byte) 0x30, utcBytes, utcBytes), 2,
+ UtcTime.TAG.getNumber(), 0x2)), false);
+ });
+ // Illegal notAfter tag
+ assertThrows(ParseException.class, () -> {
+ new Validity(new BytesReader(mutate(combine((byte) 0x30, utcBytes, utcBytes), utcBytes.length + 2,
+ UtcTime.TAG.getNumber(), 0x2)), false);
+ });
+ }
+
+ @Test
+ void testEncode() {
+ final ASN1Time utc = new UtcTime(UtcTime.TAG, null, now);
+ final ASN1Time gen = new GeneralizedTime(GeneralizedTime.TAG, null, now);
+ final Byte[] utcBytes = utc.encodeDER();
+ final Byte[] genBytes = gen.encodeDER();
+
+ assertArrayEquals(Stream.of(Arrays.asList(new Byte[]{ 0x30, (byte) (utcBytes.length + genBytes.length) }),
+ Arrays.asList(utcBytes),
+ Arrays.asList(genBytes))
+ .flatMap(Collection::stream)
+ .toArray(Byte[]::new),
+ new Validity(ASN1Object.TAG_SEQUENCE, null, utc, gen)
+ .encodeDER());
+ }
+}
diff --git a/src/test/model/pki/crl/CertificateListContentTest.java b/src/test/model/pki/crl/CertificateListContentTest.java
new file mode 100644
index 0000000..ec18629
--- /dev/null
+++ b/src/test/model/pki/crl/CertificateListContentTest.java
@@ -0,0 +1,37 @@
+package model.pki.crl;
+
+import model.TestConstants;
+import model.asn1.*;
+import model.asn1.exceptions.ParseException;
+import model.pki.AlgorithmIdentifier;
+import model.x501.AttributeTypeAndValue;
+import model.x501.Name;
+import model.x501.RelativeDistinguishedName;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+import static model.TestConstants.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class CertificateListContentTest {
+ @Test
+ void testConstructor() {
+ assertEquals(1, CRL_CONTENT_1.getVersion().getLong());
+ assertEquals("CN=Test CA", CRL_CONTENT_1.getIssuer().toString());
+ assertArrayEquals(ObjectIdentifier.OID_SHA256_WITH_RSA_ENCRYPTION,
+ CRL_CONTENT_1.getSignature().getType().getInts());
+ assertEquals(GeneralizedTime.TAG.getNumber(),
+ CRL_CONTENT_1.getThisUpdate().getTag().getNumber());
+ assertNull(CRL_CONTENT_1.getNextUpdate());
+ assertEquals(2, CRL_CONTENT_1.getRevokedCertificates().length);
+ }
+
+ @Test
+ void testEncode() {
+ assertArrayEquals(CRL_CONTENT_1_DER, CRL_CONTENT_1.encodeDER());
+ assertArrayEquals(CRL_CONTENT_2_DER, CRL_CONTENT_2.encodeDER());
+ }
+}
diff --git a/src/test/model/pki/crl/CertificateListTest.java b/src/test/model/pki/crl/CertificateListTest.java
new file mode 100644
index 0000000..0f4f06c
--- /dev/null
+++ b/src/test/model/pki/crl/CertificateListTest.java
@@ -0,0 +1,52 @@
+package model.pki.crl;
+
+import model.TestConstants;
+import model.asn1.ASN1Object;
+import model.asn1.BitString;
+import model.asn1.Null;
+import model.asn1.ObjectIdentifier;
+import model.asn1.exceptions.ParseException;
+import model.asn1.parsing.BytesReader;
+import model.pki.AlgorithmIdentifier;
+import model.pki.cert.Certificate;
+import model.pki.cert.TbsCertificate;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static model.TestConstants.combine;
+import static model.TestConstants.mutate;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class CertificateListTest {
+ private CertificateList crl;
+
+ @BeforeEach
+ void setup() {
+ crl = new CertificateList(ASN1Object.TAG_SEQUENCE, null,
+ TestConstants.CRL_CONTENT_1,
+ new AlgorithmIdentifier(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_RSA_ENCRYPTION),
+ new Null(Null.TAG, null)),
+ new BitString(BitString.TAG, null, 0, new Byte[]{ 1, 2, 3 }));
+ }
+
+ @Test
+ void testConstructor() {
+ assertEquals(2, crl.getCrl().getRevokedCertificates().length);
+ assertArrayEquals(ObjectIdentifier.OID_RSA_ENCRYPTION,
+ crl.getSignatureAlgorithm().getType().getInts());
+ assertArrayEquals(new Byte[]{ 1, 2, 3 },
+ crl.getSignature().getConvertedVal());
+ }
+
+ @Test
+ void testEncode() {
+ assertArrayEquals(combine((byte) 0x30,
+ TestConstants.CRL_CONTENT_1_DER,
+ new AlgorithmIdentifier(ASN1Object.TAG_SEQUENCE, null,
+ new ObjectIdentifier(ObjectIdentifier.TAG, null, ObjectIdentifier.OID_RSA_ENCRYPTION),
+ new Null(Null.TAG, null)).encodeDER(),
+ new BitString(BitString.TAG, null, 0, new Byte[]{ 1, 2, 3 }).encodeDER()),
+ crl.encodeDER());
+ }
+}
diff --git a/src/test/model/pki/crl/RevokedCertificateTest.java b/src/test/model/pki/crl/RevokedCertificateTest.java
new file mode 100644
index 0000000..659e421
--- /dev/null
+++ b/src/test/model/pki/crl/RevokedCertificateTest.java
@@ -0,0 +1,25 @@
+package model.pki.crl;
+
+import model.asn1.*;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+import static model.TestConstants.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class RevokedCertificateTest {
+ @Test
+ void testConstructor() {
+ assertEquals(123, REVOKED_CESSATION.getSerialNumber().getLong());
+ assertEquals(UtcTime.TAG.getNumber(), REVOKED_CESSATION.getRevocationDate().getTag().getNumber());
+ assertEquals(Reason.CESSATION_OF_OPERATION, REVOKED_CESSATION.getReason());
+ }
+
+ @Test
+ void testEncode() {
+ assertArrayEquals(REVOKED_KEY_COMPROMISE_DER, REVOKED_KEY_COMPROMISE.encodeDER());
+ }
+}