package model.pki.cert; import model.asn1.ASN1Object; import model.asn1.ASN1Time; import model.asn1.GeneralizedTime; import model.asn1.UtcTime; 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((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()); } }