0

I am trying to add additional certificates to an existing CRL using the Python cryptography project: https://cryptography.io/

Looking at the docs for the CRL builder I don't see a way to load an existing CRL, make additions with add_revoked_certificate(revoked_certificate), and then resign the CRL.

The docs for add_revoked_certificate(revoked_certificate) mention:

revoked_certificate – An instance of RevokedCertificate. These can be obtained from an existing CRL or created with RevokedCertificateBuilder.

This makes me believe that there is no out of the box way to update a CRL in place, but I just wanted to be sure I am not missing something.

For what it's worth, my current code is as below, and I inserted pseudo code as comments for what I'm trying to do.

def revoke_cert(cert_revocation_list_pem, cert_pem):
    # Load CRL
    cert_revocation_list = x509.load_pem_x509_crl(
        cert_revocation_list_pem.encode("ascii"), default_backend()
    )

    # Load cert
    cert = x509.load_pem_x509_certificate(cert_pem.encode("ascii"), default_backend())

    # Create a revoked cert
    builder = x509.RevokedCertificateBuilder()
    builder = builder.revocation_date(datetime.today())
    builder = builder.serial_number(cert.serial_number)
    revoked_cert = builder.build(default_backend())

    # I want to do something like this
    #cert_revocation_list.append(revoked_cert)

    return cert_revocation_list.public_bytes(encoding=serialization.Encoding.PEM)

As always, thanks for any help!

EDIT:

I ended up adding a third argument to accept a list of certs to revoke.

def build_crl(cert_authority_pem, private_key_pem, certs_to_revoke=None):
    # Load our root cert
    root_cert = x509.load_pem_x509_certificate(
        cert_authority_pem.encode("ascii"), default_backend()
    )

    # Load our root key
    root_key = serialization.load_pem_private_key(
        private_key_pem.encode("ascii"), password=None, backend=default_backend()
    )

    builder = x509.CertificateRevocationListBuilder()
    builder = builder.last_update(datetime.today())
    builder = builder.next_update(datetime.today() + timedelta(1, 0, 0))
    builder = builder.issuer_name(root_cert.issuer)
    if certs_to_revoke:
        for revoked_cert in certs_to_revoke:
            builder = builder.add_revoked_certificate(revoked_cert)
    cert_revocation_list = builder.sign(
        private_key=root_key, algorithm=hashes.SHA256(), backend=default_backend()
    )
    return cert_revocation_list.public_bytes(encoding=serialization.Encoding.PEM)
Joenarr Bronarsson
  • 515
  • 2
  • 5
  • 20

1 Answers1

0

Here is a detailed example of how to use cryptography: example

# cert you want to revoke
cert_to_revoke_data = open("openssl/client1.crt","rb").read()
cert_to_revoke = x509.load_pem_x509_certificate(cert_to_revoke_data, backend=default_backend())

pem_cert = open("openssl/ca.crt","rb").read()
ca_crt = x509.load_pem_x509_certificate(pem_cert, default_backend())
pem_key = open("openssl/ca.key","rb").read()
ca_key = serialization.load_pem_private_key(pem_key, password=b"test", backend=default_backend())

# load crl
pem_crl_data = open("openssl/ca.crl","rb").read()
crl = x509.load_pem_x509_crl(pem_crl_data, backend=default_backend())

# generate a new crl object
builder = x509.CertificateRevocationListBuilder()
builder = builder.issuer_name(crl.issuer)
builder = builder.last_update(crl.last_update)
builder = builder.next_update(datetime.datetime.now() + datetime.timedelta(1, 0, 0))

# add crl certificates from file to the new crl object
for i in range(0,len(crl)):    
    builder = builder.add_revoked_certificate(crl[i])

# see if the cert to be revokek already in the list    
ret = crl.get_revoked_certificate_by_serial_number(cert_to_revoke.serial_number)

# if not, then add new revoked cert
if  not isinstance(ret, x509.RevokedCertificate):
    
    revoked_cert = x509.RevokedCertificateBuilder()\
    .serial_number(cert_to_revoke.serial_number)\
    .revocation_date(datetime.datetime.now()).build(backend=default_backend())
    
    builder = builder.add_revoked_certificate(revoked_cert)

# sign and save to new crl file
cert_revocation_list = builder.sign(private_key=ca_key,algorithm=hashes.SHA256(),backend=default_backend())

with open("openssl/ca.crl","wb") as f:
    f.write(cert_revocation_list.public_bytes(serialization.Encoding.PEM))
fbzyx
  • 189
  • 1
  • 16
  • Hi fbzyx - welcome to Stack Overflow! The OP was asking a very specific, detailed question, and your answer only links to an overview of how to use the module. If you think there's a specific bit in there that answers his question, could you note that? Otherwise, this answer is unlikely to help the OP with his problem. – Paul Molodowitch Nov 11 '20 at 16:36