package persistence; import model.asn1.ASN1Object; import model.asn1.ASN1Time; import model.asn1.Int; import model.asn1.exceptions.InvalidCAException; import model.asn1.exceptions.InvalidDBException; import model.asn1.exceptions.ParseException; import model.asn1.parsing.BytesReader; import model.ca.AuditLogEntry; import model.ca.CertificationAuthority; import model.ca.Template; import model.pki.cert.Certificate; import model.pki.crl.Reason; import model.pki.crl.RevokedCertificate; import model.x501.Name; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import ui.Utils; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.Collections; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.StreamSupport; /** * Util class that encodes / decodes the CA into JSON and vice-versa. */ public class Decoder { /** * EFFECTS: Convert the list into a JSONArray using the supplied mapper and add to the JSONObject. Nothing is added * if the given list is empty. */ private static void encodeList(JSONObject o, String key, List list, Function mapper) { if (list.isEmpty()) { return; } o.put(key, new JSONArray(list.stream().map(mapper).collect(Collectors.toList()))); } /** * EFFECTS: Decode the JSONArray into a list of specific objects, using the given mapper. Return empty list if the * o does not contain key. * REQUIRES: If o contains key, it must be a JSONArray. */ private static List decodeListFromString(final JSONObject o, String key, Function mapper) { return o.keySet().contains(key) ? StreamSupport.stream(o.getJSONArray(key).spliterator(), false) .map(obj -> mapper.apply((String) obj)) .collect(Collectors.toList()) : Collections.emptyList(); } /** * EFFECTS: Decode the JSONArray into a list of specific objects, using the given mapper. Return empty list if the * o does not contain key. * REQUIRES: If o contains key, it must be a JSONArray. */ private static List decodeListFromObject(final JSONObject o, String key, Function mapper) { return o.keySet().contains(key) ? StreamSupport.stream(o.getJSONArray(key).spliterator(), false) .map(obj -> mapper.apply((JSONObject) obj)) .collect(Collectors.toList()) : Collections.emptyList(); } /** * EFFECTS: Decode the JSON object into CertificationAuthority * Throws {@link InvalidDBException} if the JSON is invalid. * Throws {@link NoSuchAlgorithmException} if RSA is not supported. * JSON should be
     *     {
     *         "key": {
     *             "n": "octet string",
     *             "p": "octet string",
     *             "e": "octet string"
     *         },
     *         "cert": "-----BEGIN CERTIFICATE-----\n...",
     *         "templates": [
     *              {
     *                  "name": "123",
     *                  "enabled": true,
     *                  "subject": "-----BEGIN DISTINGUISHED NAME-----\n...",
     *                  "validity": 100
     *              }
     *          ],
     *          "signed": [
     *              "-----BEGIN CERTIFICATE-----\n...",
     *          ],
     *          "revoked": [
     *              {
     *                  "serial": "octet string",
     *                  "date": "-----BEGIN DATE-----\n",
     *                  "reason": "KEY_COMPROMISED"
     *              }
     *          ],
     *          "logs": [
     *              {
     *                  "user": "",
     *                  "time": "ISO 8601",
     *                  "action": ""
     *              }
     *          ],
     *          "serial": 1
     *     }
     * 
* Missing fields will be default. */ public static CertificationAuthority decodeCA(JSONObject o) throws InvalidDBException, NoSuchAlgorithmException { try { Certificate caCert = o.keySet().contains("cert") ? decodeCertificate(o.getString("cert")) : null; final List