Last active
June 26, 2024 08:26
-
-
Save dayitv89/98acca6dbfb843027411cfa588b44f3b to your computer and use it in GitHub Desktop.
SSL Pinning: Get public certificate + public key + public key hash using one script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ./get_cer_key_keyhash.sh graph.facebook.com | |
# it will output three files as | |
1. graph.facebook.com_keyhash.txt | |
2. graph.facebook.com.cer | |
3. graph.facebook.com.key |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/bash | |
echo | openssl s_client -servername $1 -connect $1:443 2>/dev/null | openssl x509 -text | awk '/-----BEGIN/,/-----END CERTIFICATE-----/{print}' > $1.cer | |
echo | openssl s_client -connect $1:443 2>/dev/null | openssl x509 -pubkey -noout > $1.key | |
python get_pin_from_certificate.py $1.cer > $1_keyhash.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# credit goes to https://github.com/datatheorem/TrustKit | |
#!/usr/bin/env python2.7 | |
"""Helper script to generate a TrustKit or HPKP pin from a PEM/DER certificate file. | |
""" | |
from subprocess import Popen, PIPE | |
from sys import stdin | |
import os.path | |
import argparse | |
import hashlib | |
import base64 | |
import platform | |
class SupportedKeyAlgorithmsEnum(object): | |
RSA_2048 = 1 | |
RSA_4096 = 2 | |
ECDSA_SECP256R1 = 3 | |
ECDSA_SECP384R1 = 4 | |
if __name__ == '__main__': | |
# Parse the command line | |
parser = argparse.ArgumentParser(description='Generate HPKP / TrustKit SSL Pins.') | |
parser.add_argument('certificate', metavar='FILE', nargs='?', help='certificate file to read, if empty, stdin is used') | |
parser.add_argument('--type', dest='type', action='store', default='PEM', | |
help='Certificate file type; "PEM" (default) or "DER".') | |
args = parser.parse_args() | |
if not args.certificate: | |
certificate = stdin.read() | |
elif os.path.isfile(args.certificate): | |
with open(args.certificate, 'r') as certFile: | |
certificate = certFile.read() | |
else: | |
raise ValueError('Could not open certificate file {}'.format(args.certificate)) | |
if args.type not in ['DER', 'PEM']: | |
raise ValueError('Invalid certificate type {}; expected DER or PEM'.format(args.type)) | |
# Parse the certificate and print its information | |
p1 = Popen('openssl x509 -inform {} -text -noout'.format(args.type), shell=True, stdin=PIPE, stdout=PIPE) | |
certificate_txt = p1.communicate(input=certificate)[0] | |
print '\nCERTIFICATE INFO\n----------------' | |
p1 = Popen('openssl x509 -subject -issuer -fingerprint -sha1 -noout -inform {}'.format( | |
args.type), shell=True, stdin=PIPE, stdout=PIPE) | |
print p1.communicate(input=certificate)[0] | |
# Extract the certificate key's algorithm | |
# Tested on the output of OpenSSL 0.9.8zh and OpenSSL 1.0.2i | |
alg_txt = certificate_txt.split('Public Key Algorithm:')[1].split('\n')[0].strip() | |
key_algorithm = None | |
if alg_txt == 'id-ecPublicKey': | |
if 'prime256v1' in certificate_txt: | |
key_algorithm = SupportedKeyAlgorithmsEnum.ECDSA_SECP256R1 | |
if 'secp384r1' in certificate_txt: | |
key_algorithm = SupportedKeyAlgorithmsEnum.ECDSA_SECP384R1 | |
elif alg_txt == 'rsaEncryption': | |
if 'Key: (2048 bit)' in certificate_txt: | |
key_algorithm = SupportedKeyAlgorithmsEnum.RSA_2048 | |
elif 'Key: (4096 bit)' in certificate_txt: | |
key_algorithm = SupportedKeyAlgorithmsEnum.RSA_4096 | |
if key_algorithm is None: | |
raise ValueError('Error: Certificate key algorithm not supported: {}.'.format(alg_txt)) | |
# Generate the Subject Public Key Info hash | |
if key_algorithm == SupportedKeyAlgorithmsEnum.ECDSA_SECP256R1: | |
# The OpenSSL command is different for ECDSA secp256 | |
openssl_alg = 'ec' | |
trustkit_alg = 'kTSKAlgorithmEcDsaSecp256r1' | |
elif key_algorithm == SupportedKeyAlgorithmsEnum.ECDSA_SECP384R1: | |
# The OpenSSL command is different for ECDSA secp384 | |
openssl_alg = 'ec' | |
trustkit_alg = 'kTSKAlgorithmEcDsaSecp384r1' | |
elif key_algorithm == SupportedKeyAlgorithmsEnum.RSA_2048: | |
openssl_alg = 'rsa' | |
trustkit_alg = 'kTSKAlgorithmRsa2048' | |
elif key_algorithm == SupportedKeyAlgorithmsEnum.RSA_4096: | |
openssl_alg = 'rsa' | |
trustkit_alg = 'kTSKAlgorithmRsa4096' | |
else: | |
raise ValueError('Unexpected key algorithm') | |
if platform.system() == 'Windows': | |
cmd_redirects = '2>nul' | |
else: | |
cmd_redirects = '-in /dev/stdin 2>/dev/null' | |
p1 = Popen('openssl x509 -pubkey -noout -inform {} ' | |
'| openssl {} -outform DER -pubin {}'.format(args.type, openssl_alg, cmd_redirects), | |
shell=True, stdin=PIPE, stdout=PIPE) | |
spki = p1.communicate(input=certificate)[0] | |
spki_hash = hashlib.sha256(spki).digest() | |
hpkp_pin = base64.b64encode(spki_hash) | |
print 'TRUSTKIT CONFIGURATION\n----------------------' | |
print 'kTSKPublicKeyHashes: @[@"{}"] // You will also need to configure a backup pin'.format(hpkp_pin) | |
print 'kTSKPublicKeyAlgorithms: @[{}]\n'.format(trustkit_alg) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment