I've written a Python code to generate a cert chain using cryptography library. It involves three certificates: root, intermediate, and leaf. The root is self signed certificate, intermediate cert is signed by the root private key, and the leaf cert is signed by intermediate private key. Currently, when attempting to verify the signatures using OpenSSL, the signatures of the root and intermediate certificates are verified successfully. However, the verification fails for the leaf certificate with the following error. error 2 at 1 depth lookup: unable to get issuer certificate error verification failed. Below is the code I used to generate the certs. Please help me in finding the issue.
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.x509.oid import NameOID
import datetime
# --------------------------------------------------------------------------------------
#rootcert
root_private_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
root_subject = root_issuer = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u"RootCert")
])
builder = x509.CertificateBuilder().subject_name(
root_subject
).issuer_name(
root_issuer
).public_key(
root_private_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.now()
).not_valid_after(
datetime.datetime.now() + datetime.timedelta(days=365)
).add_extension(
x509.BasicConstraints(ca=True, path_length=None), critical=True
).add_extension(
x509.SubjectKeyIdentifier.from_public_key(root_private_key.public_key()), critical=False
).add_extension(
x509.AuthorityKeyIdentifier.from_issuer_public_key(root_private_key.public_key()), critical=False
)
cert = builder.sign(
root_private_key,
algorithm=hashes.SHA256(),
backend=default_backend()
)
der_cert = cert.public_bytes(encoding=serialization.Encoding.DER)
with open("rootcert.der", "wb") as der_file:
der_file.write(der_cert)
# --------------------------------------------------------------------------------------
#IntermediateCert
device_private_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
device_subject = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u"IntermediateCert")])
device_issuer = root_issuer
builder = x509.CertificateBuilder().subject_name(
device_subject
).issuer_name(
device_issuer
).public_key(
device_private_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.now()
).not_valid_after(
datetime.datetime.now() + datetime.timedelta(days=365)
).add_extension(
x509.BasicConstraints(ca=True, path_length=None), critical=True
).add_extension(
x509.SubjectKeyIdentifier.from_public_key(device_private_key.public_key()), critical=False
).add_extension(
x509.AuthorityKeyIdentifier.from_issuer_public_key(root_private_key.public_key()), critical=False
)
cert = builder.sign(
root_private_key,
algorithm=hashes.SHA256(),
backend=default_backend()
)
der_cert = cert.public_bytes(encoding=serialization.Encoding.DER)
with open("IntermediateCert.der", "wb") as der_file:
der_file.write(der_cert)
# --------------------------------------------------------------------------------------
#childcert
child_private_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
child_subject = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u"ChildCert")])
child_issuer = device_subject
builder = x509.CertificateBuilder().subject_name(
child_subject
).issuer_name(
child_issuer
).public_key(
child_private_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.now()
).not_valid_after(
datetime.datetime.now() + datetime.timedelta(days=365)
).add_extension(
x509.BasicConstraints(ca=False, path_length=None), critical=True
).add_extension(
x509.SubjectKeyIdentifier.from_public_key(child_private_key.public_key()), critical=False
).add_extension(
x509.AuthorityKeyIdentifier.from_issuer_public_key(device_private_key.public_key()), critical=False
)
cert = builder.sign(
device_private_key,
algorithm=hashes.SHA256(),
backend=default_backend()
)
der_cert = cert.public_bytes(encoding=serialization.Encoding.DER)
with open("childcert.der", "wb") as der_file:
der_file.write(der_cert)
There is nothing wrong with the code. I was using incorrect openssl command for verifying the cert chain.
The correct command to use is openssl verify -CAfile root.pem -untrusted inter.pem child.pem
. I was not using -untrusted option previously. For more explaination related to -untrusted can be found in this issue here.