I use cryptography to create x509 certificates. The code works as intended, but if I try to use it in pyHanko to create signer object for PDF Signing it fails. I need to register the certificate in pyHanko CertificateRegistry. In order to do that it requires issuer_serial.
I can't find any way to add some custom extension named 'issuer_serial' in order to make it work with pyHanko.
The code for creation of certificate and private key
# Generate RSA private key
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
# Generate a self-signed certificate
subject = issuer = x509.Name([
x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u"DE"), # Country
x509.NameAttribute(x509.NameOID.STATE_OR_PROVINCE_NAME, u"State"), # State
x509.NameAttribute(x509.NameOID.ORGANIZATION_NAME, u"Company"), # Organization
x509.NameAttribute(x509.NameOID.COMMON_NAME, user['name']), # User's common name
x509.NameAttribute(x509.NameOID.EMAIL_ADDRESS, user['email']) # User's email
])
cert_builder = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.utcnow())
.not_valid_after(datetime.utcnow() + timedelta(days=365))
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
.sign(private_key, algorithm=hashes.SHA256(), backend=default_backend())
)
# Serialize private key to PEM format
private_key_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
# Serialize certificate to PEM format
cert_pem = cert_builder.public_bytes(encoding=serialization.Encoding.PEM)
# Generate a random Fernet key for encryption
fernet_key = Fernet.generate_key()
# Encrypt the private key using Fernet encryption
f = Fernet(fernet_key)
encrypted_private_key = f.encrypt(private_key_pem)
# Encode encrypted private key and fernet key to base64
encrypted_private_key_base64 = base64.b64encode(encrypted_private_key).decode('utf-8')
fernet_key_base64 = base64.b64encode(fernet_key).decode('utf-8')
The part that fails in pyHanko code for registration:
cert_store = CertificateRegistry() # Create an instance of CertificateRegistry
cert_store.register(cert_pem) # Register the certificate
Code to create signer object:
cms_signer = signers.SimpleSigner(
private_key,
cert,
cert_registry=cert_store,
)