From 69a630ac27e3894b1f1725cf172e670a26011cfa Mon Sep 17 00:00:00 2001 From: "core.equip" Date: Wed, 16 Oct 2019 16:03:25 +0200 Subject: [PATCH 1/2] Added pinning for the whole certificate chain. --- .../javapinning/PinningTrustManager.java | 8 +++-- .../integrationtest/IntegrationTest.java | 15 +++++++-- tools/pin.groovy | 33 +++++++++++++++++++ version.gradle | 4 +-- 4 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 tools/pin.groovy diff --git a/java-pinning-core/src/main/java/eu/geekplace/javapinning/PinningTrustManager.java b/java-pinning-core/src/main/java/eu/geekplace/javapinning/PinningTrustManager.java index bfddca8..4cea40d 100644 --- a/java-pinning-core/src/main/java/eu/geekplace/javapinning/PinningTrustManager.java +++ b/java-pinning-core/src/main/java/eu/geekplace/javapinning/PinningTrustManager.java @@ -43,10 +43,12 @@ public void checkClientTrusted(X509Certificate[] chain, String authType) @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + final X509Certificate leafCertificate = chain[0]; - if (isPinned(leafCertificate)) { - return; - } + + for (X509Certificate cert: chain) + if (isPinned(cert)) return; + // Throw a CertificateException with a meaningful message. Note that we // use CERTPLAIN, which tends to be long, so colons as separator are of // no use and most other software UIs show the "public key" without diff --git a/java-pinning-core/src/test/java/eu/geekplace/javapinning/integrationtest/IntegrationTest.java b/java-pinning-core/src/test/java/eu/geekplace/javapinning/integrationtest/IntegrationTest.java index 005e06d..ed162ad 100644 --- a/java-pinning-core/src/test/java/eu/geekplace/javapinning/integrationtest/IntegrationTest.java +++ b/java-pinning-core/src/test/java/eu/geekplace/javapinning/integrationtest/IntegrationTest.java @@ -31,10 +31,21 @@ public class IntegrationTest { + private static final String PIN_GITHUB_DIGICERT = "SHA256:451335746aa70c5b022570531e4cb5eaf8b5a1b3a50a01459ffc8e848ff2fa1a"; + private static final String PIN_GITHUB_LEAF = "SHA256:a39a1ae45e0b6d911f799d245c3826694d8adec20f62d6d0a53dc440b259aae3"; + + @Test + public void testGithubDigiCert() throws NoSuchAlgorithmException, KeyManagementException, IOException { + connect(JavaPinning.forPin(PIN_GITHUB_DIGICERT)); + } + @Test - public void main() throws NoSuchAlgorithmException, KeyManagementException, IOException { - SSLContext sc = JavaPinning.forPin("SHA256:a4bd7ea9bf474cc459266b82fdb07f648f5ddf4d8162baea895b91c96f831ab5"); + public void testGithubLeaf() throws NoSuchAlgorithmException, KeyManagementException, IOException { + connect(JavaPinning.forPin(PIN_GITHUB_LEAF)); + } + + private void connect(SSLContext sc) throws NoSuchAlgorithmException, KeyManagementException, IOException { Socket socket = new Socket("github.com", 443); SSLSocket sslSocket = (SSLSocket) sc.getSocketFactory().createSocket(socket, "github.com", 443, true); sslSocket.startHandshake(); diff --git a/tools/pin.groovy b/tools/pin.groovy new file mode 100644 index 0000000..5875522 --- /dev/null +++ b/tools/pin.groovy @@ -0,0 +1,33 @@ +import javax.net.ssl.HttpsURLConnection +import java.security.MessageDigest +import java.security.cert.Certificate +import java.security.cert.X509Certificate + +def domain = args.size() ? args[0] : null +if (!domain) { + println 'Usage: pin.groovy ' + System.exit(0) +} + +def con = "https://$domain".toURL().openConnection() as HttpsURLConnection +con.connect() + +con.getServerCertificates().eachWithIndex { Certificate cert, int i -> + + println "Certificate Nr. ${i + 1}" + if (!cert instanceof X509Certificate) return + + def xc = cert as X509Certificate + + println "Subject: ${xc.subjectDN.name}" + println "Valid from ${xc.notBefore} to ${xc.notAfter}" + + if (xc.subjectAlternativeNames?.size()) + println "Alternate DNS: ${xc.subjectAlternativeNames*.last().join(', ')}" + + def sha = new BigInteger(1, MessageDigest.getInstance('SHA-256').digest(cert.publicKey.encoded)) + .toString(16).padLeft(64, '0').toLowerCase() + + println "Pin string: SHA256:$sha\n" +} +con.disconnect() \ No newline at end of file diff --git a/version.gradle b/version.gradle index 0f0b6a7..38d0b7e 100644 --- a/version.gradle +++ b/version.gradle @@ -1,10 +1,10 @@ allprojects { ext { - shortVersion = '1.2.1' + shortVersion = '1.2.2' // increase versionCode with every release // versionCode format: // - versionCode = 01020100 + versionCode = 01020200 isSnapshot = true } } From 66d815bcd2a1c9e98e7ee0235b7292ec1fede875 Mon Sep 17 00:00:00 2001 From: "core.equip" Date: Wed, 16 Oct 2019 16:11:57 +0200 Subject: [PATCH 2/2] Fixed whitespace. --- .../main/java/eu/geekplace/javapinning/PinningTrustManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-pinning-core/src/main/java/eu/geekplace/javapinning/PinningTrustManager.java b/java-pinning-core/src/main/java/eu/geekplace/javapinning/PinningTrustManager.java index 4cea40d..fa62c4f 100644 --- a/java-pinning-core/src/main/java/eu/geekplace/javapinning/PinningTrustManager.java +++ b/java-pinning-core/src/main/java/eu/geekplace/javapinning/PinningTrustManager.java @@ -46,7 +46,7 @@ public void checkServerTrusted(X509Certificate[] chain, String authType) final X509Certificate leafCertificate = chain[0]; - for (X509Certificate cert: chain) + for (X509Certificate cert : chain) if (isPinned(cert)) return; // Throw a CertificateException with a meaningful message. Note that we