package model.pki.cert; import annotations.Assoc; import model.asn1.ASN1Object; import model.asn1.Encodable; import model.asn1.Tag; import model.asn1.exceptions.ParseException; import model.asn1.parsing.BytesReader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; /** * Represents an X.509 certificate extensions list: *
 *     Extensions ::= SEQUENCE OF Extension
 * 
*/ public class Extensions extends ASN1Object { /** * The extension array. */ @Assoc(partOf = true) private final Extension[] extensions; /** * EFFECT: Initialize with the given tags and extensions. For tag and parentTag, consult * {@link ASN1Object}. * REQUIRES: Extensions should have SEQUENCE tag. */ public Extensions(Tag tag, Tag parentTag, Extension[] extensions) { super(tag, parentTag); this.extensions = extensions; } /** * EFFECT: Parse the Name from input DER bytes. For details on parsing, refer to {@link ASN1Object}. * Throws {@link ParseException} for invalid input. * MODIFIES: this, encoded */ public Extensions(BytesReader encoded, boolean hasParentTag) throws ParseException { super(encoded, hasParentTag); final List list = new ArrayList<>(); for (int i = 0; i < getLength(); ) { int index = encoded.getIndex(); final Extension ext = new Extension(encoded, false); ext.getTag().enforce(TAG_SEQUENCE); list.add(ext); index = encoded.getIndex() - index; i += index; } this.extensions = list.toArray(new Extension[0]); } /** * EFFECTS: Encode the SEQUENCE OF into DER, keep order. RDNs will be encoded one-by-one. */ @Override public Byte[] encodeValueDER() { return Stream.of(extensions) .map(Encodable::encodeDER) .flatMap(Arrays::stream) .toArray(Byte[]::new); } public Extension[] getExtensions() { return extensions; } }