nohup
nohup

Reputation: 3165

converting pem file to encrypted private key file of PBES1 format in Python

I am writing a program where I am trying to convert the certs, which is of pem format into PBES1 private key (the one with -----BEGIN ENCRYPTED PRIVATE KEY----- and -----END ENCRYPTED PRIVATE KEY----- header and footer.)

Below is the code I wrote. I am specific about the encryption algorithm used here for compatibility reasons. I was initially trying to use utf-8 encoding, but it gave me

UnicodeDecodeError: 'utf-8' codec can't decode »(,¾æ0x82 in position 1: invalid start byte

hence I changed it to latin-1, but please correct me if I am wrong here.

from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.serialization import PrivateFormat, pkcs12
from cryptography import x509
from cryptography.hazmat.backends import default_backend


def get_CN(crt_subject: x509.Name) -> str:
    return next(attr.value for attr in crt_subject if attr.oid == x509.NameOID.COMMON_NAME)


def pkcs12_pbes1(password: str, pkey, clcert, cacerts: list[x509.Certificate]) -> bytes:
    encryption_algorithm = (
        PrivateFormat.PKCS12.encryption_builder()
        .kdf_rounds(30)
        .key_cert_algorithm(pkcs12.PBES.PBESv1SHA1And3KeyTripleDESCBC)
        .hmac_hash(hashes.SHA256())
        .build(password.encode("latin-1"))
        )

    return pkcs12.serialize_key_and_certificates(
        name=get_CN(clcert.subject).encode("latin-1"),
        key=pkey,
        cert=clcert,
        cas=cacerts,
        encryption_algorithm=encryption_algorithm,
    )


def load_ec_private_key_from_pem(file_path):
    try:
        with open(file_path, 'rb') as pem_file:
            pem_data = pem_file.read()
        private_key = serialization.load_pem_private_key(
            pem_data,
            password=None,  # Assuming the private key is not password-protected
            backend=default_backend()
        )
        return private_key
    except Exception as e:
        print("Error:", e)
        return None


def read_pem_file(file_path):
    try:
        with open(file_path, 'rb') as pem_file:
            pem_data = pem_file.read()
        p_cert = x509.load_pem_x509_certificate(pem_data)
        return p_cert
    except FileNotFoundError:
        print(f"Error: File '{file_path}' not found.")
        return None
    

p_cert = read_pem_file('test_cert.pem')
p_key = load_ec_private_key_from_pem('test_key.pem')
p_ca = read_pem_file('test_ca.pem')

pbes1_pem = pkcs12_pbes1("somepasswd", p_key, p_cert, [p_ca])
print(pbes1_pem.decode('latin-1'))

Upon testing, I am able to read my test cert, key and ca from the file and the pbes1_pem seems to be a binary array in encrypted form. However, I fail to write it to another file of encrypted private key pem format like below

-----BEGIN ENCRYPTED PRIVATE KEY-----
data
-----END ENCRYPTED PRIVATE KEY-----

I was going through the hazmat documentation and I couldn't find a helper function that could convert the encrypted binary array into the above mentioned specified format. Is this the part where I need to base64 encode the data myself and add it within those header and footer manually, or is there a helper function that I'm missing? Any help is appreciated.

Thanks.

Upvotes: 1

Views: 134

Answers (0)

Related Questions