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?
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)
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))