Skip to content

Instantly share code, notes, and snippets.

@ryanchapman
Last active June 12, 2020 20:11
Show Gist options
  • Save ryanchapman/69adee6379d215099af90b023005e311 to your computer and use it in GitHub Desktop.
Save ryanchapman/69adee6379d215099af90b023005e311 to your computer and use it in GitHub Desktop.
Print certificate signatures that can be used with certificate pinning on iOS and Android
#!/usr/bin/env python
#
# Print certificate signatures that can be used with certificate pinning on iOS and Android
#
# usage: cat cert_bundle.pem | ./print_cert_signatures.py
# usage: openssl s_client -connect fqdn:443 -showcerts </dev/null 2>/dev/null | ~/bin/print_cert_signatures.py
#
# example:
# $ openssl s_client -connect www.google.com:443 -showcerts </dev/null 2>/dev/null | ~/bin/print_cert_signatures.py
# Certificate 1 of 2:
# Key Type: RSA-2048
# Subject: C=US, ST=California, L=Mountain View, O=Google LLC, CN=www.google.com
# Issuer: C=US, O=Google Trust Services, CN=GTS CA 1O1
# Pubkey Signature: mcc0YcAK2ejMs6RabSa5fpKGi2zQFUyVcisQEktcjqs=
# Certificate 2 of 2:
# Key Type: RSA-2048
# Subject: C=US, O=Google Trust Services, CN=GTS CA 1O1
# Issuer: OU=GlobalSign Root CA - R2, O=GlobalSign, CN=GlobalSign
# Pubkey Signature: YZPgTZ+woNCCCIW3LH2CxQeLzB/1m42QcCTBSdgayjs=
import base64
import datetime
import hashlib
import sys
from OpenSSL.crypto import load_certificate, dump_certificate, dump_publickey, TYPE_DSA, TYPE_EC, TYPE_RSA, FILETYPE_PEM, FILETYPE_ASN1
def pem_header_string():
return '-----BEGIN CERTIFICATE-----'
def pem_footer_string():
return '-----END CERTIFICATE-----'
def seek_to_cert_beginning():
found = False
for line in sys.stdin:
if pem_header_string() in line:
found = True
break
else:
continue
return found
def read_pem_certs_from_stdin():
certs = []
while seek_to_cert_beginning() != False:
# can't rewind stdin, so manually copy the header, and later, the footer
cert = pem_header_string() + '\n'
for line in sys.stdin:
if pem_footer_string() in line:
break
else:
cert += line
cert += pem_footer_string()
certs.append(cert)
return certs
def get_keytype(x509cert):
kt = x509cert.get_pubkey().type()
keytypes = {
TYPE_RSA: 'RSA',
TYPE_DSA: 'DSA',
TYPE_EC: 'EC'
}
return keytypes.get(kt, 'Unknown keytype {}'.format(kt))
def component_list_to_string(components):
str = ''
continued = False
for c in components:
if continued:
str += ', '
str += '{}={}'.format(c[0], c[1])
continued = True
return str
def get_issuer(x509cert):
issuer = component_list_to_string(x509cert.get_issuer().get_components())
return issuer
def get_issuer_expiration(x509cert):
not_after = x509cert.get_notAfter()
return not_after
def get_subject(x509cert):
subject = component_list_to_string(x509cert.get_subject().get_components())
return subject
def get_subject_expiration(x509cert):
not_after = x509cert.get_notAfter()
return not_after
def get_pubkey_signature_base64(x509cert):
pubkey = x509cert.get_pubkey()
pubkey_der = dump_publickey(FILETYPE_ASN1, pubkey)
return base64.b64encode(hashlib.sha256(pubkey_der).digest())
def get_cert_signature_base64(x509cert):
cert_der = dump_certificate(FILETYPE_ASN1, x509cert)
return base64.b64encode(hashlib.sha256(cert_der).digest())
def print_certs():
certs = read_pem_certs_from_stdin()
num_certs = len(certs)
i = 1
for certpem in certs:
x509cert = load_certificate(FILETYPE_PEM, certpem)
keytype = get_keytype(x509cert)
issuer = get_issuer(x509cert)
issuer_expiration = datetime.datetime.strptime(get_issuer_expiration(x509cert).decode('ascii'), r'%Y%m%d%H%M%SZ')
subject = get_subject(x509cert)
subject_expiration = datetime.datetime.strptime(get_subject_expiration(x509cert).decode('ascii'), r'%Y%m%d%H%M%SZ')
cert_sig_b64 = get_cert_signature_base64(x509cert)
pubkey_sig_b64 = get_pubkey_signature_base64(x509cert)
print 'Certificate {} of {}:'.format(i, num_certs)
print ' Key Type: {}-{}'.format(keytype, x509cert.get_pubkey().bits())
print ' Subject: {}'.format(subject)
print ' Subject Expiration: {}'.format(subject_expiration)
print ' Issuer: {}'.format(issuer)
print ' Issuer Expiration: {}'.format(issuer_expiration)
print ' Cert Signature: {}'.format(cert_sig_b64)
print ' Pubkey Signature: {}'.format(pubkey_sig_b64)
i += 1
def main():
print_certs()
if __name__=='__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment