[tor-commits] [flashproxy/master] Check every certificate's public key, not only the leaf's.

dcf at torproject.org dcf at torproject.org
Thu Aug 1 03:13:30 UTC 2013


commit e234f31d8c1017672a2000925a0e8ff4f32feda8
Author: David Fifield <david at bamsoftware.com>
Date:   Thu Jul 11 15:26:51 2013 -0700

    Check every certificate's public key, not only the leaf's.
    
    I put the Chromium kSPKIHash_Google1024 as the only allowed key, as
    that's the one I see right now.
---
 facilitator/facilitator-email-poller |   29 +++++++++++++++++------------
 flashproxy-reg-appspot               |   32 +++++++++++++++++---------------
 flashproxy-reg-email                 |   24 +++++++++++++++++-------
 3 files changed, 51 insertions(+), 34 deletions(-)

diff --git a/facilitator/facilitator-email-poller b/facilitator/facilitator-email-poller
index a2b5cd6..8b9f10a 100755
--- a/facilitator/facilitator-email-poller
+++ b/facilitator/facilitator-email-poller
@@ -64,9 +64,11 @@ A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
 # SHA-1 digest of expected public keys. Any of these is valid. See
 # http://www.imperialviolet.org/2011/05/04/pinning.html for the reason behind
 # hashing the public key, not the entire certificate.
-PUBKEY_SHA1 = tuple(x.decode("hex") for x in (
-    "63c445c009328b663cdff9cb68f6c523ac7b6c2b",
-))
+PUBKEY_SHA1 = (
+    # https://src.chromium.org/viewvc/chrome/trunk/src/net/http/transport_security_state_static.h?revision=209003&view=markup
+    # kSPKIHash_Google1024
+    "\x40\xc5\x40\x1d\x6f\x8c\xba\xf0\x8b\x00\xed\xef\xb1\xee\x87\xd0\x05\xb3\xb9\xcd",
+)
 
 LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
 
@@ -362,15 +364,18 @@ def imap_login():
     finally:
         ca_certs_file.close()
 
-    # Check that the public key is what we expect.
-    cert = imap.ssl().get_peer_cert()
-    pubkey_der = cert.get_pubkey().as_der()
-    pubkey_digest = sha1(pubkey_der).digest()
-
-    if options.use_certificate_pin and pubkey_digest not in PUBKEY_SHA1:
-        expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"
-        raise ValueError("Public key does not match pin: got %s but expected any of %s" %
-            (pubkey_digest.encode("hex"), expected))
+    if options.use_certificate_pin:
+        found = []
+        for cert in imap.ssl().get_peer_cert_chain():
+            pubkey_der = cert.get_pubkey().as_der()
+            pubkey_digest = sha1(pubkey_der).digest()
+            if pubkey_digest in PUBKEY_SHA1:
+                break
+            found.append(pubkey_digest)
+        else:
+            found = "(" + ", ".join(x.encode("hex") for x in found) + ")"
+            expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"
+            raise ValueError("Public key does not match pin: got %s but expected any of %s" % (found, expected))
 
     log(u"logging in as %s" % options.email_addr)
     imap.login(options.email_addr, email_password)
diff --git a/flashproxy-reg-appspot b/flashproxy-reg-appspot
index fc960e9..2ca3467 100755
--- a/flashproxy-reg-appspot
+++ b/flashproxy-reg-appspot
@@ -63,12 +63,11 @@ A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
 # SHA-1 digest of expected public keys. Any of these is valid. See
 # http://www.imperialviolet.org/2011/05/04/pinning.html for the reason behind
 # hashing the public key, not the entire certificate.
-PUBKEY_SHA1 = tuple(x.decode("hex") for x in (
-    "c70ccd442ff4528c603aefef85206fd693990e09",
-    "1697e17a8a3317f031721b7b6293cd50643bbbd3",
-    "291e750bafedac444486327e50f26f64d840991a",
-    "1e3f66cfa0eb03136297fdb238ad6619c30ff375",
-))
+PUBKEY_SHA1 = (
+    # https://src.chromium.org/viewvc/chrome/trunk/src/net/http/transport_security_state_static.h?revision=209003&view=markup
+    # kSPKIHash_Google1024
+    "\x40\xc5\x40\x1d\x6f\x8c\xba\xf0\x8b\x00\xed\xef\xb1\xee\x87\xd0\x05\xb3\xb9\xcd",
+)
 
 class options(object):
     address_family = socket.AF_UNSPEC
@@ -234,15 +233,18 @@ class PinHTTPSConnection(httplib.HTTPSConnection):
         self.sock = SSL.Connection(ctx, sock)
         self.sock.connect((self.host, self.port))
 
-        # Check that the public key is what we expect.
-        cert = self.sock.get_peer_cert()
-        pubkey_der = cert.get_pubkey().as_der()
-        pubkey_digest = sha1(pubkey_der).digest()
-
-        if options.use_certificate_pin and pubkey_digest not in PUBKEY_SHA1:
-            expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"
-            raise ValueError("Public key does not match pin: got %s but expected any of %s" %
-                (pubkey_digest.encode("hex"), expected))
+        if options.use_certificate_pin:
+            found = []
+            for cert in self.sock.get_peer_cert_chain():
+                pubkey_der = cert.get_pubkey().as_der()
+                pubkey_digest = sha1(pubkey_der).digest()
+                if pubkey_digest in PUBKEY_SHA1:
+                    break
+                found.append(pubkey_digest)
+            else:
+                found = "(" + ", ".join(x.encode("hex") for x in found) + ")"
+                expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"
+                raise ValueError("Public key does not match pin: got %s but expected any of %s" % (found, expected))
 
 class PinHTTPSHandler(urllib2.HTTPSHandler):
     def https_open(self, req):
diff --git a/flashproxy-reg-email b/flashproxy-reg-email
index a3c27ad..6d3f092 100755
--- a/flashproxy-reg-email
+++ b/flashproxy-reg-email
@@ -60,9 +60,11 @@ A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
 # SHA-1 digest of expected public keys. Any of these is valid. See
 # http://www.imperialviolet.org/2011/05/04/pinning.html for the reason behind
 # hashing the public key, not the entire certificate.
-PUBKEY_SHA1 = tuple(x.decode("hex") for x in (
-    "69ba4a72fc198b2203ecdf0c75493e4d5300dac9",
-))
+PUBKEY_SHA1 = (
+    # https://src.chromium.org/viewvc/chrome/trunk/src/net/http/transport_security_state_static.h?revision=209003&view=markup
+    # kSPKIHash_Google1024
+    "\x40\xc5\x40\x1d\x6f\x8c\xba\xf0\x8b\x00\xed\xef\xb1\xee\x87\xd0\x05\xb3\xb9\xcd",
+)
 
 # Registrations are encrypted with this public key before being emailed. Only
 # the facilitator operators should have the corresponding private key. Given a
@@ -284,10 +286,18 @@ try:
     smtp.sock.connect_ssl()
     smtp.file = smtp.sock.makefile()
 
-    # Check that the public key is what we expect.
-    cert = smtp.sock.get_peer_cert()
-    pubkey_der = cert.get_pubkey().as_der()
-    pubkey_digest = sha1(pubkey_der).digest()
+    if options.use_certificate_pin:
+        found = []
+        for cert in smtp.sock.get_peer_cert_chain():
+            pubkey_der = cert.get_pubkey().as_der()
+            pubkey_digest = sha1(pubkey_der).digest()
+            if pubkey_digest in PUBKEY_SHA1:
+                break
+            found.append(pubkey_digest)
+        else:
+            found = "(" + ", ".join(x.encode("hex") for x in found) + ")"
+            expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"
+            raise ValueError("Public key does not match pin: got %s but expected any of %s" % (found, expected))
 
     if options.use_certificate_pin and pubkey_digest not in PUBKEY_SHA1:
         expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"





More information about the tor-commits mailing list