aboutsummaryrefslogtreecommitdiff
path: root/src/main/ui/Utils.java
blob: ccb244e7991b9d894a6b8dec5f487693d440d957 (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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package ui;

import model.asn1.exceptions.ParseException;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * Useful small methods for the whole program.
 */
public final class Utils {
    /**
     * EFFECTS: Convert the input primitive byte array into the boxed Byte array.
     */
    public static Byte[] byteToByte(byte[] array) {
        Byte[] arr = new Byte[array.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = array[i];
        }
        return arr;
    }

    /**
     * EFFECTS: Convert the input boxed Byte array into primitive byte array.
     */
    public static byte[] byteToByte(Byte[] array) {
        byte[] arr = new byte[array.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = array[i];
        }
        return arr;
    }

    /**
     * EFFECTS: Pack the big-endian bytes into a 32bit integer.
     *   Throws {@link model.asn1.exceptions.ParseException} if the value is too large.
     */
    public static int bytesToInt(Byte[] array) throws ParseException {
        try {
            return new BigInteger(byteToByte(array)).intValueExact();
        } catch (ArithmeticException ignored) {
            throw new ParseException("Value is too large.");
        }
    }

    /**
     * EFFECTS: Pack the big-endian bytes into a 64bit integer.
     *   Throws {@link model.asn1.exceptions.ParseException} if the value is too large.
     */
    public static long bytesToLong(Byte[] array) throws ParseException {
        try {
            return new BigInteger(byteToByte(array)).longValueExact();
        } catch (ArithmeticException ignored) {
            throw new ParseException("Value is too large.");
        }
    }

    /**
     * EFFECTS: Unpack the multibyte 64bit integer to its shortest array of byte format.
     */
    public static Byte[] valToByte(long val) {
        byte[] v = BigInteger.valueOf(val).toByteArray();
        if (val != 0 && v[0] == 0) {
            if (v.length == 1) {
                return new Byte[0];
            }
            byte[] arr = new byte[v.length - 1];
            System.arraycopy(v, 1, arr, 0, arr.length);
            return byteToByte(arr);
        }
        return byteToByte(v);
    }

    /**
     * EFFECTS: Parse the two-digit octet string into an unsigned byte, preserving leading zero and negative values.
     * REQUIRES: The input octet must be a two-char string, with each char matching [0-9][A-F].
     */
    public static Byte parseByte(String octet) {
        return (byte) Integer.parseInt(octet, 16);
    }

    /**
     * EFFECTS: Decode the input PEM file, with optional check on tags.
     *   Throws {@link ParseException} if the desiredTag is specified but the input does not have the specific tag, or
     *   if the input does not have any tags at all (not a PEM).
     */
    public static Byte[] parsePEM(Byte[] input, String desiredTag) throws ParseException {
        final String str = new String(byteToByte(input), StandardCharsets.UTF_8);
        Pattern pattern =
                Pattern.compile("^-----BEGIN " + desiredTag
                                + "-----$\n^(.*)$\n^-----END " + desiredTag + "-----$",
                        Pattern.DOTALL | Pattern.MULTILINE);
        final Matcher matcher = pattern.matcher(str);
        if (!matcher.matches()) {
            throw new ParseException("Not a valid PEM");
        }
        final String b64 = matcher.group(1).replace("\n", "");
        return byteToByte(Base64.getDecoder().decode(b64));
    }
}