pythoncertificatex509certificatefingerprintpycryptodome

Generating fingerprint from X509 certificate using Pycryptodome


I'm trying to generate the same SHA1 fingerprint for a X509 certificate using pycryptodome that I get from the openssl command:

openssl x509 -noout -fingerprint -sha1 -inform pem -in certificate.crt

My certificate is in PEM format on disk

However, the code snippet below gives me a different value.

from Crypto.PublicKey import RSA
import hashlib

contents = open("/home/ubuntu/certificate.crt", "r").read().encode()
certificate = RSA.import_key(contents)
bytes = certificate.export_key("DER")
hashlib.sha1(bytes).hexdigest()

Anyone any idea what I'm doing wrong?


Solution

  • The code uses only PyCryptodome to print the fingerprint of an X.509 certificate:

    from Crypto.Hash import SHA1
    from Crypto.IO import PEM
    
    filename = "cert.pem"
    
    pem_data = open(filename, "r").read()
    der = PEM.decode(pem_data)
    
    h = SHA1.new()
    h.update(der[0])
    fingerprint = h.hexdigest()
    
    print(fingerprint)
    

    Documentation:

    Crypto.IO.PEM.decode(pem_data, passphrase=None)

    Crypto.Hash.SHA1()

    The following example implements basic error checking for the certificate and prepends the hex string to 40 characters so that it is a valid kid:

    """
    This code reads an X.509 certificate and prints the SHA-1 fingerprint in hex
    """
    
    import sys
    import re
    from Crypto.Hash import SHA1
    from Crypto.IO import PEM
    
    def get_fingerprint(fname):
        """
        Read an X.509 certificate and return the SHA-1 fingerprint in hex
        """
    
        with open(fname, "r", encoding="utf-8") as f:
            pem_data = f.read()
    
        r = re.compile(r"\s*-----BEGIN (.*)-----\s+")
        m = r.match(pem_data)
        marker = m.group(1)
    
        if marker != "CERTIFICATE":
            print("Error: Expected X.509 Certificate")
            sys.exit(1)
    
        der = PEM.decode(pem_data)
    
        h = SHA1.new()
        h.update(der[0])
        fingerprint = h.hexdigest()
    
        # insert leading zero bytes to make the string 40 digits
        while len(fingerprint) < 40:
            fingerprint = '0' + fingerprint
    
        return fingerprint
    
    if __name__ == '__main__':
        filename = "cert1.pem"
    
        print(get_fingerprint(filename))