From 265f081ad3db3fd6028a1c5573462e5a2eea973a Mon Sep 17 00:00:00 2001 From: INOPIAE Date: Sat, 15 Dec 2018 12:05:06 +0100 Subject: [PATCH] add: show sha-1 and sha-256 fingerprint on certificate page Change-Id: I9feb13ab227ed85dd640f3757996556a0f01e69b --- src/club/wpia/gigi/dbObjects/Certificate.java | 19 +++++++++++ .../account/certs/CertificateDisplay.templ | 9 +++-- .../pages/account/certs/Certificates.java | 11 +++++-- .../wpia/gigi/dbObjects/TestCertificate.java | 33 +++++++++++++++++++ 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/club/wpia/gigi/dbObjects/Certificate.java b/src/club/wpia/gigi/dbObjects/Certificate.java index 0654a416..c46b1b47 100644 --- a/src/club/wpia/gigi/dbObjects/Certificate.java +++ b/src/club/wpia/gigi/dbObjects/Certificate.java @@ -4,6 +4,9 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -16,6 +19,8 @@ import java.util.List; import java.util.Locale; import java.util.Map.Entry; +import javax.xml.bind.DatatypeConverter; + import club.wpia.gigi.GigiApiException; import club.wpia.gigi.database.DBEnum; import club.wpia.gigi.database.GigiPreparedStatement; @@ -649,4 +654,18 @@ public class Certificate implements IdCachable { } return new BigInteger(serial, 16); } + + public String getFingerprint(String algorithm) throws IOException, GeneralSecurityException, GigiApiException { + X509Certificate certx = cert(); + return getFingerprint(certx, algorithm); + } + + private static String getFingerprint(X509Certificate cert, String algorithm) throws NoSuchAlgorithmException, CertificateEncodingException { + MessageDigest md = MessageDigest.getInstance(algorithm); + byte[] der = cert.getEncoded(); + md.update(der); + byte[] digest = md.digest(); + String digestHex = DatatypeConverter.printHexBinary(digest); + return digestHex.toLowerCase(); + } } diff --git a/src/club/wpia/gigi/pages/account/certs/CertificateDisplay.templ b/src/club/wpia/gigi/pages/account/certs/CertificateDisplay.templ index 9aad7bcb..f2aaf870 100644 --- a/src/club/wpia/gigi/pages/account/certs/CertificateDisplay.templ +++ b/src/club/wpia/gigi/pages/account/certs/CertificateDisplay.templ @@ -83,10 +83,13 @@ - : - + : + + + + : + - :
diff --git a/src/club/wpia/gigi/pages/account/certs/Certificates.java b/src/club/wpia/gigi/pages/account/certs/Certificates.java index 40faa1f1..9c0dafd0 100644 --- a/src/club/wpia/gigi/pages/account/certs/Certificates.java +++ b/src/club/wpia/gigi/pages/account/certs/Certificates.java @@ -183,8 +183,15 @@ public class Certificates extends Page implements HandlesMixedRequest { vars.put("DN", c.getDistinguishedName()); vars.put("digest", c.getMessageDigest()); vars.put("profile", c.getProfile().getVisibleName()); - vars.put("fingerprint", "TBD"); // TODO function needs to be - // implemented in Certificate.java + try { + vars.put("fingerprintSHA1", c.getFingerprint("sha-1")); + vars.put("fingerprintSHA256", c.getFingerprint("sha-256")); + } catch (GeneralSecurityException e) { + e.printStackTrace(); + } catch (GigiApiException e) { + e.format(out, l, getDefaultVars(req)); + } + try { if (st == CertificateStatus.ISSUED || st == CertificateStatus.REVOKED) { diff --git a/tests/club/wpia/gigi/dbObjects/TestCertificate.java b/tests/club/wpia/gigi/dbObjects/TestCertificate.java index 0b4d6549..5321ba19 100644 --- a/tests/club/wpia/gigi/dbObjects/TestCertificate.java +++ b/tests/club/wpia/gigi/dbObjects/TestCertificate.java @@ -9,6 +9,7 @@ import java.security.KeyPair; import org.junit.Test; import club.wpia.gigi.GigiApiException; +import club.wpia.gigi.database.GigiPreparedStatement; import club.wpia.gigi.dbObjects.Certificate.AttachmentType; import club.wpia.gigi.dbObjects.Certificate.CSRType; import club.wpia.gigi.testUtils.ClientBusinessTest; @@ -77,4 +78,36 @@ public class TestCertificate extends ClientBusinessTest { assertEquals(u, c.getActor()); assertEquals("AB", c.getActor().getInitials()); } + + @Test + public void testFingerprint() throws IOException, GeneralSecurityException, GigiApiException { + Certificate c = importCertificate(); + assertEquals("fa6175b369627d47a52b9fd73e87ccf087afbd10", c.getFingerprint("sha-1")); + assertEquals("98c3f2a5424d2404e0b2ccdae17d8cbc949ea36bddb0c3f152a931f88c17c3d3", c.getFingerprint("sha-256")); + } + + private Certificate importCertificate() throws GigiApiException { + int certID; + try (GigiPreparedStatement inserter = new GigiPreparedStatement("INSERT INTO certs SET md=?::`mdType`, csr_type=?::`csrType`, memid=?, profile=?, actorid=?, created=NOW(), caid=?, expire=NOW()")) { + inserter.setString(1, Digest.SHA512.toString().toLowerCase()); + inserter.setString(2, CSRType.CSR.toString()); + inserter.setInt(3, u.getId()); + inserter.setInt(4, 10); + inserter.setInt(5, u.getId()); + inserter.setInt(6, 4); + inserter.execute(); + certID = inserter.lastInsertId(); + } + + try (GigiPreparedStatement insertAVA = new GigiPreparedStatement("INSERT INTO `certAvas` SET `certId`=?, name=?, value=?")) { + insertAVA.setInt(1, certID); + insertAVA.setString(2, "EMAIL"); + insertAVA.setString(3, u.getEmail()); + insertAVA.execute(); + } + Certificate c = Certificate.getById(certID); + String pem = "-----BEGIN CERTIFICATE-----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-----END CERTIFICATE-----"; + c.addAttachment(AttachmentType.CRT, pem); + return c; + } } -- 2.39.2