From 376ad64d4bafc4b2db6990604758addf8fabbd3c Mon Sep 17 00:00:00 2001 From: Benny Baumann Date: Thu, 19 Oct 2017 01:25:59 +0200 Subject: [PATCH] add: initial class for performing arbitrary checks to validate public keys Change-Id: Ia7813913b1f5922747ddba4af9a21e4fbaf07c9e --- src/club/wpia/gigi/crypto/key/KeyCheck.java | 59 +++++++++++++++++++ .../account/certs/CertificateRequest.java | 8 ++- .../wpia/gigi/crypto/key/KeyCheckTest.java | 36 +++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 src/club/wpia/gigi/crypto/key/KeyCheck.java create mode 100644 tests/club/wpia/gigi/crypto/key/KeyCheckTest.java diff --git a/src/club/wpia/gigi/crypto/key/KeyCheck.java b/src/club/wpia/gigi/crypto/key/KeyCheck.java new file mode 100644 index 00000000..7c1ed82b --- /dev/null +++ b/src/club/wpia/gigi/crypto/key/KeyCheck.java @@ -0,0 +1,59 @@ +package club.wpia.gigi.crypto.key; + +import java.security.PublicKey; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import club.wpia.gigi.GigiApiException; + +public abstract class KeyCheck { + + protected static final Set checks = new LinkedHashSet(); + + public static List getChecks() { + return Collections.list(Collections.enumeration(checks)); + } + + public static void register(KeyCheck check) { + checks.add(check); + } + + public abstract void check(PublicKey key) throws GigiApiException; + + public static void checkKey(PublicKey key) throws GigiApiException { + + if (checks.isEmpty()) { + // Mandatory checks are registered here + } + + if (key == null) { + throw new GigiApiException("Failed key sanity check: No key given!"); + } + + for (KeyCheck kc : checks) { + kc.check(key); + } + + } + + @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } + + if (o == this) { + return true; + } + + return getClass().equals(o.getClass()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } + +} diff --git a/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java b/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java index 4158e9ba..8a1bc594 100644 --- a/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java +++ b/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java @@ -16,6 +16,7 @@ import java.util.TreeSet; import club.wpia.gigi.GigiApiException; import club.wpia.gigi.crypto.SPKAC; +import club.wpia.gigi.crypto.key.KeyCheck; import club.wpia.gigi.dbObjects.Certificate; import club.wpia.gigi.dbObjects.Certificate.CSRType; import club.wpia.gigi.dbObjects.Certificate.SANType; @@ -108,7 +109,7 @@ public class CertificateRequest { this(c, csr, (CertificateProfile) null); } - public CertificateRequest(AuthorizationContext ctx, String csr, CertificateProfile cp) throws GeneralSecurityException, IOException, IOException { + public CertificateRequest(AuthorizationContext ctx, String csr, CertificateProfile cp) throws GeneralSecurityException, IOException, IOException, GigiApiException { this.ctx = ctx; if (cp != null) { profile = cp; @@ -190,6 +191,8 @@ public class CertificateRequest { } this.SANs = SANs; pk = parsed.getSubjectPublicKeyInfo(); + KeyCheck.checkKey(pk); + String sign = getSignatureAlgorithm(data); guessDigest(sign); @@ -206,12 +209,13 @@ public class CertificateRequest { throw new GigiApiException("Challenge mismatch"); } pk = parsed.getPubkey(); + KeyCheck.checkKey(pk); + String sign = getSignatureAlgorithm(data); guessDigest(sign); this.SANs = new HashSet<>(); this.csr = "SPKAC=" + cleanedSPKAC; this.csrType = CSRType.SPKAC; - } private static String getSignatureAlgorithm(byte[] data) throws IOException { diff --git a/tests/club/wpia/gigi/crypto/key/KeyCheckTest.java b/tests/club/wpia/gigi/crypto/key/KeyCheckTest.java new file mode 100644 index 00000000..203e830a --- /dev/null +++ b/tests/club/wpia/gigi/crypto/key/KeyCheckTest.java @@ -0,0 +1,36 @@ +package club.wpia.gigi.crypto.key; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.PublicKey; + +import org.junit.Test; + +import sun.security.util.DerValue; +import sun.security.x509.X509Key; +import club.wpia.gigi.GigiApiException; +import club.wpia.gigi.util.PEM; + +public class KeyCheckTest { + + public static PublicKey pkFromString(String pub) throws GeneralSecurityException, IOException { + byte[] data = PEM.decode("PUBLIC KEY", pub); + DerValue der = new DerValue(data); + PublicKey key = X509Key.parse(der); + + return key; + } + + @Test + public void testNullKey() { + try { + KeyCheck.checkKey(null); + fail("Providing a null key should fail!"); + } catch (GigiApiException gae) { + assertTrue(true); + } + } + +} -- 2.39.2