package model.x501; 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: *
 *   AttributeTypeAndValue ::= SEQUENCE {
 *       type ATTRIBUTE.&id({SupportedAttributes}),
 *       value ATTRIBUTE.&Type({SupportedAttributes}{@type}),
 *   ... }
 * 
*/ public class AttributeTypeAndValue extends ASN1Object { /** * The type of that attribute. For example,
2.5.4.10
is OU. * It determines the format of the value. */ @Assoc(partOf = true) private final ObjectIdentifier type; /** * Value corresponding to type. */ @Assoc(partOf = true) private final ASN1Object value; /** * 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. */ public AttributeTypeAndValue(Tag tag, Tag parentTag, ObjectIdentifier type, ASN1Object value) { super(tag, parentTag); this.type = type; this.value = value; } /** * EFFECTS: Parse input DER. Value is not checked against the type. * Throws {@link ASN1Object} if invalid: * - Any fields missing * - 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 AttributeTypeAndValue(BytesReader encoded, boolean hasParentTag) throws ParseException { super(encoded, hasParentTag); this.type = new ObjectIdentifier(encoded, false); this.type.getTag().enforce(ObjectIdentifier.TAG); this.value = ASN1Object.parse(encoded, false); } /** * EFFECTS: Encode the fields into DER, in the order. */ @Override public Byte[] encodeValueDER() { return Stream.of(Arrays.asList(type.encodeDER()), Arrays.asList(value.encodeDER())) .flatMap(Collection::stream) .toArray(Byte[]::new); } /** * EFFECTS: Return in TYPE=Value format. Type will be either x.x.x.x.x or human-readable strings like CN. Value is * input-defined. ',' '+' '=' will be escaped. */ @Override public String toString() { return type.toString().replace(",", "\\,") .replace("=", "\\=") .replace("+", "\\+") + "=" + value.toString().replace(",", "\\,") .replace("=", "\\=") .replace("+", "\\+"); } public ObjectIdentifier getType() { return type; } public ASN1Object getValue() { return value; } }