0

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,
    )
KROLN
  • 300
  • 1
  • 13
  • I'm not familiar with pyHanko but why do you believe you need a custom extension called 'issuer_serial'? Every certificate already has a serial number chosen by the issuer. – President James K. Polk Aug 13 '23 at 14:54
  • Yes but pyHanko for some reason want to get something what is called: AttributeError: 'cryptography.hazmat.bindings._rust.x509.Certificat' object has no attribute 'issuer_serial' https://pyhanko.readthedocs.io/en/latest/api-docs/pyhanko_certvalidator.html#pyhanko_certvalidator.registry.CertificateCollection.retrieve_by_issuer_serial – KROLN Aug 13 '23 at 15:08
  • This is why questions **must include details of the errors or problems you're having**. In python an attribute is like a "field" in an object. For example, `x=object();x.issuer_serial` will give you the same error. This is not an error about something missing in a certificate, although it may ultimately be caused by that. It would help me, and perhaps others, if you could edit your question to include a [mre] along with the full exception stacktrace. – President James K. Polk Aug 13 '23 at 16:11

0 Answers0