aboutsummaryrefslogtreecommitdiff
path: root/src/main/ui
diff options
context:
space:
mode:
authorYuuta Liang <yuutaw@student.cs.ubc.ca>2023-10-26 05:00:12 +0800
committerYuuta Liang <yuutaw@student.cs.ubc.ca>2023-10-26 05:00:12 +0800
commit578b7d1db256d9a582cef45ae5d13d858a977416 (patch)
treeb856cc5af32a0d649321f501f2966d013cade6c0 /src/main/ui
parentf73bca3372a31f360d894dcbe8580cef779af739 (diff)
downloadjca-578b7d1db256d9a582cef45ae5d13d858a977416.tar
jca-578b7d1db256d9a582cef45ae5d13d858a977416.tar.gz
jca-578b7d1db256d9a582cef45ae5d13d858a977416.tar.bz2
jca-578b7d1db256d9a582cef45ae5d13d858a977416.zip
Add persistence
Signed-off-by: Yuuta Liang <yuutaw@student.cs.ubc.ca>
Diffstat (limited to 'src/main/ui')
-rw-r--r--src/main/ui/IssueScreen.java8
-rw-r--r--src/main/ui/JCA.java95
-rw-r--r--src/main/ui/MainScreen.java6
-rw-r--r--src/main/ui/MgmtScreen.java3
-rw-r--r--src/main/ui/TemplateSetScreen.java8
-rw-r--r--src/main/ui/TemplatesScreen.java2
-rw-r--r--src/main/ui/Utils.java6
7 files changed, 105 insertions, 23 deletions
diff --git a/src/main/ui/IssueScreen.java b/src/main/ui/IssueScreen.java
index 5e3ad50..3e70a0a 100644
--- a/src/main/ui/IssueScreen.java
+++ b/src/main/ui/IssueScreen.java
@@ -4,6 +4,7 @@ import model.asn1.exceptions.ParseException;
import model.ca.Template;
import model.csr.CertificationRequest;
import model.pki.cert.Certificate;
+import model.x501.Name;
/**
* The screen that accepts a CSR and template and allows user to change its properties and issue.
@@ -65,6 +66,7 @@ public class IssueScreen implements UIHandler {
public void commit() {
try {
Certificate certificate = session.getCa().signCert(incomingCSR.getCertificationRequestInfo(), template);
+ session.save();
System.out.println(Utils.toPEM(certificate.encodeDER(), "CERTIFICATE"));
session.setScreen(Screen.MAIN);
} catch (Throwable e) {
@@ -78,7 +80,11 @@ public class IssueScreen implements UIHandler {
*/
private void handleIssueSetSubject(String val) {
try {
- template = new Template(template.getName(), template.isEnabled(), val, template.getValidity());
+ if (val == null) {
+ template = new Template(template.getName(), template.isEnabled(), (Name) null, template.getValidity());
+ } else {
+ template = new Template(template.getName(), template.isEnabled(), val, template.getValidity());
+ }
} catch (ParseException e) {
System.out.println(e.getMessage());
}
diff --git a/src/main/ui/JCA.java b/src/main/ui/JCA.java
index 882c546..420ec10 100644
--- a/src/main/ui/JCA.java
+++ b/src/main/ui/JCA.java
@@ -1,9 +1,14 @@
package ui;
+import model.asn1.exceptions.InvalidDBException;
import model.asn1.exceptions.ParseException;
import model.ca.CertificationAuthority;
+import persistence.Decoder;
+import persistence.FS;
+import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Scanner;
@@ -13,6 +18,11 @@ import java.util.Scanner;
*/
public class JCA {
/**
+ * Default db file (./data/ca.json)
+ */
+ private static final Path PATH_DEFAULT = Path.of("data", "ca.json");
+
+ /**
* Instances of the five screens;
*/
private final UIHandler mainScreen;
@@ -23,13 +33,18 @@ public class JCA {
/**
* The CA
*/
- private final CertificationAuthority ca;
+ private CertificationAuthority ca;
/**
* The current screen.
*/
private UIHandler screen;
/**
+ * There are unsaved changes.
+ */
+ private boolean unsaved = false;
+
+ /**
* EFFECTS: Init with main screen and empty CA. No private key and no CA cert.
* Throws {@link NoSuchAlgorithmException} when crypto issue happens.
*/
@@ -106,34 +121,72 @@ public class JCA {
screen.enter(args);
}
+ /**
+ * EFFECTS: Read the database file and replace all local states.
+ * MODIFIES: this
+ */
+ private void load() {
+ if (unsaved) {
+ System.out.println("Current database is not saved yet.");
+ return;
+ }
+ try {
+ this.ca = Decoder.decodeCA(FS.read(PATH_DEFAULT));
+ } catch (InvalidDBException | NoSuchAlgorithmException e) {
+ System.out.println(e.getMessage());
+ if (e.getCause() != null) {
+ System.out.println(e.getCause().getMessage());
+ e.getCause().printStackTrace();
+ }
+ }
+ }
+
private void handleLine(String... args) {
if (args[0].equals("log")) {
ca.getLogs().forEach(System.out::println);
return;
}
- switch (args[0]) {
- case "help":
- screen.help();
- System.out.println("log\tView audit logs");
- break;
- case "show":
- screen.show();
- break;
- case "commit":
- screen.commit();
- break;
- case "exit":
- setScreen(screen.exit());
- break;
- default:
- screen.command(args);
- break;
+ if ("help".equals(args[0])) {
+ screen.help();
+ System.out.println("log\tView audit logs");
+ System.out.println("load\tLoad database");
+ System.out.println("save\tSave database");
+ } else if ("commit".equals(args[0])) {
+ screen.commit();
+ } else if ("show".equals(args[0])) {
+ screen.show();
+ } else if ("exit".equals(args[0])) {
+ setScreen(screen.exit());
+ } else if ("save".equals(args[0])) {
+ save();
+ } else if ("load".equals(args[0])) {
+ load();
+ } else {
+ screen.command(args);
}
printPS1();
}
+ /**
+ * EFFECTS: Print the '*user@JCA PS1' line
+ */
private void printPS1() {
- System.out.printf("%s@JCA %s ", ca.getUser(), screen.getPS1());
+ System.out.printf("%s%s@JCA %s ",
+ unsaved ? "*" : "",
+ ca.getUser(),
+ screen.getPS1());
+ }
+
+ /**
+ * EFFECTS: Save the DB
+ */
+ public void save() {
+ try {
+ FS.write(PATH_DEFAULT, Decoder.encodeCA(ca));
+ unsaved = false;
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
}
/**
@@ -152,6 +205,10 @@ public class JCA {
}
}
+ public void setUnsaved(boolean unsaved) {
+ this.unsaved = unsaved;
+ }
+
public CertificationAuthority getCa() {
return ca;
}
diff --git a/src/main/ui/MainScreen.java b/src/main/ui/MainScreen.java
index 2eaf882..8a85881 100644
--- a/src/main/ui/MainScreen.java
+++ b/src/main/ui/MainScreen.java
@@ -7,6 +7,7 @@ import model.asn1.parsing.BytesReader;
import model.ca.Template;
import model.csr.CertificationRequest;
import model.pki.cert.Certificate;
+import model.pki.crl.CertificateList;
import model.pki.crl.Reason;
import model.pki.crl.RevokedCertificate;
@@ -138,6 +139,7 @@ public class MainScreen implements UIHandler {
session.getCa().revoke(new RevokedCertificate(ASN1Object.TAG_SEQUENCE, null,
c.getCertificate().getSerialNumber(),
new UtcTime(UtcTime.TAG, null, ZonedDateTime.now(ZoneId.of("UTC"))), reason));
+ session.save();
} catch (IllegalArgumentException ignored) {
System.out.println("Illegal serial number or reason");
}
@@ -177,7 +179,9 @@ public class MainScreen implements UIHandler {
return;
}
try {
- System.out.println(Utils.toPEM(session.getCa().signCRL().encodeDER(), "X509 CRL"));
+ CertificateList crl = session.getCa().signCRL();
+ session.save();
+ System.out.println(Utils.toPEM(crl.encodeDER(), "X509 CRL"));
} catch (Throwable e) {
System.out.println(e.getMessage());
}
diff --git a/src/main/ui/MgmtScreen.java b/src/main/ui/MgmtScreen.java
index 0a25bfe..c630a34 100644
--- a/src/main/ui/MgmtScreen.java
+++ b/src/main/ui/MgmtScreen.java
@@ -73,6 +73,7 @@ public class MgmtScreen implements UIHandler {
try {
CertificationRequest req = session.getCa().signCSR();
System.out.println(Utils.toPEM(req.encodeDER(), "CERTIFICATE REQUEST"));
+ session.setUnsaved(true);
} catch (Throwable e) {
System.out.println(e.getMessage());
}
@@ -90,6 +91,7 @@ public class MgmtScreen implements UIHandler {
final Byte[] in = session.handleInputPEM("CERTIFICATE");
final Certificate cert = new Certificate(new BytesReader(in), false);
session.getCa().installCertificate(cert);
+ session.setUnsaved(true);
} catch (InvalidCAException | ParseException e) {
System.out.println(e.getMessage());
}
@@ -105,6 +107,7 @@ public class MgmtScreen implements UIHandler {
}
try {
session.getCa().generateKey();
+ session.setUnsaved(true);
} catch (NoSuchAlgorithmException e) {
System.out.println(e.getMessage());
}
diff --git a/src/main/ui/TemplateSetScreen.java b/src/main/ui/TemplateSetScreen.java
index a0b39c1..30d25b9 100644
--- a/src/main/ui/TemplateSetScreen.java
+++ b/src/main/ui/TemplateSetScreen.java
@@ -2,6 +2,7 @@ package ui;
import model.asn1.exceptions.ParseException;
import model.ca.Template;
+import model.x501.Name;
/**
* The screen that modifies the properties of a single template and add it to the store.
@@ -36,7 +37,11 @@ public class TemplateSetScreen implements UIHandler {
*/
private void handleSetSubject(String val) {
try {
- template = new Template(template.getName(), template.isEnabled(), val, template.getValidity());
+ if (val == null) {
+ template = new Template(template.getName(), template.isEnabled(), (Name) null, template.getValidity());
+ } else {
+ template = new Template(template.getName(), template.isEnabled(), val, template.getValidity());
+ }
} catch (ParseException e) {
System.out.println(e.getMessage());
}
@@ -94,6 +99,7 @@ public class TemplateSetScreen implements UIHandler {
@Override
public void commit() {
session.getCa().addTemplate(template);
+ session.setUnsaved(true);
session.setScreen(Screen.TEMPLATES);
}
diff --git a/src/main/ui/TemplatesScreen.java b/src/main/ui/TemplatesScreen.java
index e08df50..e622709 100644
--- a/src/main/ui/TemplatesScreen.java
+++ b/src/main/ui/TemplatesScreen.java
@@ -75,6 +75,7 @@ public class TemplatesScreen implements UIHandler {
return;
}
session.getCa().setTemplateEnable(tmp, enable);
+ session.setUnsaved(true);
}
/**
@@ -92,6 +93,7 @@ public class TemplatesScreen implements UIHandler {
return;
}
session.getCa().removeTemplate(tmp);
+ session.setUnsaved(true);
}
/**
diff --git a/src/main/ui/Utils.java b/src/main/ui/Utils.java
index f653ffa..4a9beeb 100644
--- a/src/main/ui/Utils.java
+++ b/src/main/ui/Utils.java
@@ -80,7 +80,11 @@ public final class Utils {
throw new ParseException("Not a valid PEM");
}
final String b64 = matcher.group(1).replace("\n", "");
- return byteToByte(Base64.getDecoder().decode(b64));
+ try {
+ return byteToByte(Base64.getDecoder().decode(b64));
+ } catch (IllegalArgumentException e) {
+ throw new ParseException(e.getMessage());
+ }
}
/**