Skip to content

Instantly share code, notes, and snippets.

@jpf
Created March 3, 2015 02:15
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jpf/a82e5bc0e086b629f11b to your computer and use it in GitHub Desktop.
Save jpf/a82e5bc0e086b629f11b to your computer and use it in GitHub Desktop.
How to implmement TLS Public Key Pinning in Python (Sort of modeled after HKPK)
import urllib3
from urllib3 import HTTPSConnectionPool
import certifi
import base64
import M2Crypto
import hashlib
class TestHTTPSConnectionPool(HTTPSConnectionPool):
def _validate_conn(self, conn):
super(TestHTTPSConnectionPool, self)._validate_conn(conn)
pinset = [
'c22be239f483c08957bc106219cc2d3ac1a308dfbbdd0a365f17b9351234cf00'
]
if not conn.is_verified:
return False
der = conn.sock.getpeercert(binary_form=True)
x509 = M2Crypto.X509.load_cert_string(der, M2Crypto.X509.FORMAT_DER)
mem = M2Crypto.BIO.MemoryBuffer()
public_key = x509.get_pubkey().get_rsa().save_pub_key_bio(mem)
pk_der = mem.getvalue().split("\n")[1:-2]
pk_base64 = ''.join(pk_der)
pk_raw = base64.b64decode(pk_base64)
pk_sha265 = hashlib.sha256(pk_raw).hexdigest()
if pk_sha265 in pinset:
pass
else:
raise Exception("Public Key not found in pinset!")
pool = TestHTTPSConnectionPool(
'example.com',
443,
cert_reqs='CERT_REQUIRED',
ca_certs=certifi.where())
rv = pool.urlopen('GET', 'https://example.com/')
print rv.data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment