package model.asn1; import model.asn1.exceptions.ParseException; import model.asn1.parsing.BytesReader; import ui.Utils; import java.nio.charset.StandardCharsets; /** * Represents an ASN.1 string with an optional character set restriction. Users should choose from one of its * implementations that encode a specific ASN.1 string type (e.g., {@link PrintableString} or {@link IA5String}). */ public abstract class ASN1String extends ASN1Object { private String rawString; /** * EFFECTS: Constructs an ASN1String with the given tag, parent tag, and string. * - Throws {@link ParseException} if the string does not pass corresponding restrictions of the specific * string type (same as {@link ASN1String#validate(String)}) * REQUIRES: For the requirements of tag and parentTag, consult {@link ASN1Object}. */ public ASN1String(Tag tag, Tag parentTag, String string) throws ParseException { super(tag, parentTag); setString(string); } /** * EFFECTS: Parse the input value. See {@link ASN1Object} with the rawString. * Throws {@link ParseException} when invalid: * - String does not pass type restrictions * - Early EOF * - Other cases as seen in {@link ASN1Object} * MODIFIES: this, encoded (bytes are read) */ public ASN1String(BytesReader encoded, boolean hasParentTag) throws ParseException { super(encoded, hasParentTag); } /** * EFFECTS: Validate and set the string. * Throws {@link ParseException} if the string is invalid. * MODIFIES: this */ protected void setString(String rawString) throws ParseException { if (!validate(rawString)) { throw new ParseException(String.format("The string '%s' is illegal for '%s'.", rawString, getClass().getSimpleName())); } this.rawString = rawString; } /** * EFFECTS: Validate whether the given string matches the ASN.1 restrictions on this specific string type. By * default, it always returns true. */ protected boolean validate(String newString) { return true; } /** * Same as {@link ASN1String#getString()}. */ @Override public String toString() { return rawString; } /** * EFFECTS: Encode the string in DER bytes (big-endian UTF-8). */ @Override public Byte[] encodeValueDER() { final byte[] bytes = rawString.getBytes(StandardCharsets.UTF_8); Byte[] b = new Byte[bytes.length]; for (int i = 0; i < bytes.length; i++) { b[i] = bytes[i]; } return b; } public String getString() { return rawString; } }