aboutsummaryrefslogtreecommitdiff
path: root/src/main/ui/MgmtScreen.java
diff options
context:
space:
mode:
authorYuuta Liang <yuutaw@students.cs.ubc.ca>2023-10-14 05:12:06 +0800
committerYuuta Liang <yuutaw@students.cs.ubc.ca>2023-10-14 05:12:06 +0800
commit0bcc057e741af3fbc108f42b75f9d42f48f6a51e (patch)
treed638c81c0778554a8902efc59000e61db74060be /src/main/ui/MgmtScreen.java
parentf369da34cf9aca151df0150d90e651e6a88ee700 (diff)
downloadjca-0bcc057e741af3fbc108f42b75f9d42f48f6a51e.tar
jca-0bcc057e741af3fbc108f42b75f9d42f48f6a51e.tar.gz
jca-0bcc057e741af3fbc108f42b75f9d42f48f6a51e.tar.bz2
jca-0bcc057e741af3fbc108f42b75f9d42f48f6a51e.zip
Implement the CA
Signed-off-by: Yuuta Liang <yuutaw@students.cs.ubc.ca>
Diffstat (limited to 'src/main/ui/MgmtScreen.java')
-rw-r--r--src/main/ui/MgmtScreen.java170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/main/ui/MgmtScreen.java b/src/main/ui/MgmtScreen.java
new file mode 100644
index 0000000..613aa50
--- /dev/null
+++ b/src/main/ui/MgmtScreen.java
@@ -0,0 +1,170 @@
+package ui;
+
+import model.asn1.ASN1Object;
+import model.asn1.BitString;
+import model.asn1.Bool;
+import model.asn1.ObjectIdentifier;
+import model.asn1.exceptions.ParseException;
+import model.asn1.parsing.BytesReader;
+import model.csr.CertificationRequest;
+import model.pki.SubjectPublicKeyInfo;
+import model.pki.cert.Certificate;
+import model.pki.cert.Extension;
+import model.pki.cert.TbsCertificate;
+
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.BitSet;
+
+public class MgmtScreen implements UIHandler {
+ private final JCA session;
+
+ /**
+ * EFFECTS: Init with the parent session.
+ */
+ public MgmtScreen(JCA session) {
+ this.session = session;
+ }
+
+ @Override
+ public void help() {
+ System.out.print("show\tView the public key and CA certificate\n"
+ + "csr\tGenerate a CSR for a upper-level CA to sign\n"
+ + "install\tInstall a CA certificate\n"
+ + "exit\tGo to main menu\n"
+ + "help\tPrint this message\n");
+ }
+
+ /**
+ * EFFECTS: Format the public key and CA
+ */
+ @Override
+ public void show() {
+ System.out.printf("Public Key:\t%s\n",
+ Base64.getEncoder().encodeToString(session.getCa().getPublicKey().getEncoded()));
+ if (!session.checkCA(true)) {
+ return;
+ }
+ final TbsCertificate info = session.getCa().getCertificate().getCertificate();
+ System.out.printf("Subject:\t%s\n", info.getSubject().toString());
+ System.out.printf("Issuer:\t%s\n", info.getIssuer().toString());
+ System.out.printf("Not Before:\t%s\n", info.getValidity().getNotBefore().getTimestamp());
+ System.out.printf("Not After:\t%s\n", info.getValidity().getNotAfter().getTimestamp());
+ System.out.printf("Signature:\t%s\n",
+ Base64.getEncoder().encodeToString(Utils.byteToByte(info.getSubjectPublicKeyInfo()
+ .getSubjectPublicKey().getConvertedVal())));
+ }
+
+ private void handleCSR() {
+ if (!session.checkCA(false)) {
+ return;
+ }
+ try {
+ CertificationRequest req = session.getCa().signCSR();
+ System.out.println(Utils.toPEM(req.encodeDER(), "CERTIFICATE REQUEST"));
+ session.log("Signed CA CSR.");
+ } catch (Throwable e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ private void validateCACertificateVersion(Certificate cert) throws ParseException {
+ if (cert.getCertificate().getVersion() == null
+ || cert.getCertificate().getVersion().getLong() != TbsCertificate.VERSION_V3) {
+ throw new ParseException("The input certificate must be V3");
+ }
+ }
+
+ private void validateCACertificatePublicKey(Certificate cert) throws ParseException {
+ final SubjectPublicKeyInfo expectedPKInfo = session.getCa().getCAPublicKeyInfo();
+ if (!Arrays.equals(cert.getCertificate().getSubjectPublicKeyInfo().getAlgorithm().getType().getInts(),
+ expectedPKInfo.getAlgorithm().getType().getInts())
+ || !Arrays.equals(cert.getCertificate().getSubjectPublicKeyInfo().getSubjectPublicKey().getVal(),
+ expectedPKInfo.getSubjectPublicKey().getVal())) {
+ throw new ParseException("The input certificate does not have the corresponding public key");
+ }
+ }
+
+ private void validateCACertificateBasicConstraints(Certificate cert) throws ParseException {
+ final Extension basicConstraints = cert.getCertificate().getExtension(ObjectIdentifier.OID_BASIC_CONSTRAINTS);
+ if (basicConstraints == null
+ || basicConstraints.getExtnValue().getBytes().length <= 0) {
+ throw new ParseException("The certificate does not have a valid basicConstraints extension.");
+ }
+ final ASN1Object basicConstraintsValue =
+ new ASN1Object(new BytesReader(basicConstraints.getExtnValue().getBytes()), false);
+ if (basicConstraintsValue.getLength() <= 0) {
+ throw new ParseException("The certificate does not have a valid basicConstraints extension.");
+ }
+ final ASN1Object bool =
+ ASN1Object.parse(new BytesReader(basicConstraintsValue.encodeValueDER()), false);
+ if (!(bool instanceof Bool)
+ || !((Bool) bool).getValue()) {
+ throw new ParseException("The certificate does not have a valid basicConstraints extension.");
+ }
+ }
+
+ private void validateCACertificateKeyUsage(Certificate cert) throws ParseException {
+ final Extension keyUsage = cert.getCertificate().getExtension(ObjectIdentifier.OID_KEY_USAGE);
+ if (keyUsage == null
+ || keyUsage.getExtnValue().getBytes().length <= 0) {
+ throw new ParseException("The certificate does not have a valid keyUsage extension.");
+ }
+ final ASN1Object keyUsageValue =
+ ASN1Object.parse(new BytesReader(keyUsage.getExtnValue().getBytes()), false);
+ if (keyUsageValue.getLength() <= 0
+ || !(keyUsageValue instanceof BitString)) {
+ throw new ParseException("The certificate does not have a valid keyUsage extension.");
+ }
+ final BitSet bitSet = BitSet.valueOf(Utils.byteToByte(((BitString) keyUsageValue).getVal()));
+ if (!bitSet.get(7) || !bitSet.get(2) || !bitSet.get(1)) {
+ throw new ParseException("The certificate does not have a valid keyUsage extension.");
+ }
+ }
+
+ private void handleInstall() {
+ if (!session.checkCA(false)) {
+ return;
+ }
+ try {
+ final Byte[] in = session.handleInputPEM("CERTIFICATE");
+ Certificate cert = new Certificate(new BytesReader(in), false);
+ validateCACertificateVersion(cert);
+ validateCACertificatePublicKey(cert);
+ validateCACertificateBasicConstraints(cert);
+ validateCACertificateKeyUsage(cert);
+ session.getCa().installCertificate(cert);
+ session.log("A CA certificate is installed.");
+ } catch (ParseException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ @Override
+ public void command(String... args) {
+ switch (args[0]) {
+ case "csr":
+ handleCSR();
+ break;
+ case "install":
+ handleInstall();
+ break;
+ default:
+ help();
+ break;
+ }
+ }
+
+ /**
+ * EFFECTS: Go to main menu
+ */
+ @Override
+ public Screen exit() {
+ return Screen.MAIN;
+ }
+
+ @Override
+ public String getPS1() {
+ return "/ca/ #";
+ }
+} \ No newline at end of file