package model.csr; import annotations.Assoc; import model.asn1.ASN1Object; import model.asn1.ObjectIdentifier; import model.asn1.Tag; import model.asn1.exceptions.ParseException; import model.asn1.parsing.BytesReader; import java.util.Arrays; import java.util.Collection; import java.util.stream.Stream; /** * Implements the following: *
 *   Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
 *       type   ATTRIBUTE.&id({IOSet}),
 *       values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
 *   }
 * 
*

* Represents a key - values pair in the CSR attribute. */ public class Attribute extends ASN1Object { /** * The type of that attribute. For example,

2.5.29.14
is subjectKeyIdentifier. * It determines the format of the value. */ @Assoc(partOf = true) private final ObjectIdentifier type; /** * Value set. */ @Assoc(partOf = true) private final Values values; /** * EFFECT: Init the object with tag, parentTag, type, and values. For tag and parentTag, see {@link ASN1Object}. * REQUIRES: The values must match the type. Type tag should be UNIVERSAL OID, and values should be SET OF. */ public Attribute(Tag tag, Tag parentTag, ObjectIdentifier type, Values values) { super(tag, parentTag); this.type = type; this.values = values; } /** * EFFECTS: Parse input DER. Value is not checked against the type. * Throws {@link ASN1Object} if invalid: * - Any fields missing (info, algorithm, signature) * - Any fields having an incorrect tag (as seen in the ASN.1 definition) * - Any fields with encoding instructions that violate implicit / explicit encoding rules * - Other issues found during parsing the object, like early EOF (see {@link ASN1Object}) * MODIFIES: this, encoded */ public Attribute(BytesReader encoded, boolean hasParentTag) throws ParseException { super(encoded, hasParentTag); this.type = new ObjectIdentifier(encoded, false); this.type.getTag().enforce(ObjectIdentifier.TAG); this.values = new Values(encoded, false); this.values.getTag().enforce(TAG_SET); } /** * EFFECTS: Encode the fields into DER, in the order. */ @Override public Byte[] encodeValueDER() { return Stream.of(Arrays.asList(type.encodeDER()), Arrays.asList(values.encodeDER())) .flatMap(Collection::stream) .toArray(Byte[]::new); } public ObjectIdentifier getType() { return type; } public Values getValues() { return values; } }