From 578b7d1db256d9a582cef45ae5d13d858a977416 Mon Sep 17 00:00:00 2001 From: Yuuta Liang Date: Thu, 26 Oct 2023 05:00:12 +0800 Subject: Add persistence Signed-off-by: Yuuta Liang --- src/main/persistence/Decoder.java | 284 ++++++++++++++++++++++++++++++++++++++ src/main/persistence/FS.java | 46 ++++++ 2 files changed, 330 insertions(+) create mode 100644 src/main/persistence/Decoder.java create mode 100644 src/main/persistence/FS.java (limited to 'src/main/persistence') diff --git a/src/main/persistence/Decoder.java b/src/main/persistence/Decoder.java new file mode 100644 index 0000000..799a4ad --- /dev/null +++ b/src/main/persistence/Decoder.java @@ -0,0 +1,284 @@ +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