aboutsummaryrefslogtreecommitdiff
path: root/src/main/model/asn1/ASN1String.java
blob: 148c564a5550332748ab30ac468a3413828a37d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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;
    }
}