如何修改Python证书生成代码以支持CA签发(对应OpenSSL相关参数)
实现CA签发证书的Python代码修改方案
要替代你给出的OpenSSL命令openssl x509 -req -CAkey key.pem -CA CA.CRT -CAcreateserial -in csr.csr -days 365 -out cert.CRT -extfile config.conf -extensions v3_req,需要把原有的自签名证书生成代码改成CA签发逻辑,具体修改如下:
核心修改要点
- 新增CA证书、CA私钥、CSR文件的读取逻辑,对应OpenSSL的
-CA、-CAkey、-in参数 - 实现序列号自动生成/递增逻辑,对应
-CAcreateserial参数 - 分离证书的主体(来自CSR)和签发者(来自CA证书)
- 使用CA私钥完成签名,而非用户自身密钥
修改后的完整代码
from cryptography import x509 from cryptography.x509.oid import NameOID from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.backends import default_backend import datetime from datetime import timedelta import os def ca_sign_cert(csr_path, output_crt_path, ca_crt_path, ca_key_path, serial_path=None, days=365): # 读取并解析CA证书(对应-CA CA.CRT) with open(ca_crt_path, "rb") as f: ca_cert = x509.load_pem_x509_certificate(f.read(), default_backend()) # 读取并解析CA私钥(对应-CAkey key.pem,若私钥有密码需添加password参数) with open(ca_key_path, "rb") as f: ca_private_key = serialization.load_pem_private_key( f.read(), password=None, backend=default_backend() ) # 读取并解析CSR(对应-in csr.csr) with open(csr_path, "rb") as f: csr = x509.load_pem_x509_csr(f.read(), default_backend()) # 处理序列号(对应-CAcreateserial) if serial_path is None: # 默认将serial文件放在CA证书同一目录下 serial_path = os.path.join(os.path.dirname(ca_crt_path), "serial") serial_number = None if os.path.exists(serial_path): # 读取现有序列号并递增 with open(serial_path, "r") as f: serial_str = f.read().strip() serial_number = int(serial_str, 16) + 1 else: # 首次生成时用随机序列号 serial_number = x509.random_serial_number() # 将新序列号写入文件(十六进制格式) with open(serial_path, "w") as f: f.write(f"{serial_number:08x}\n") # 构建证书 cert_builder = x509.CertificateBuilder() # 证书主体来自CSR的请求信息 cert_builder = cert_builder.subject_name(csr.subject) # 签发者为CA证书的主体 cert_builder = cert_builder.issuer_name(ca_cert.subject) # 公钥来自CSR cert_builder = cert_builder.public_key(csr.public_key()) # 设置生成的序列号 cert_builder = cert_builder.serial_number(serial_number) # 有效期设置 cert_builder = cert_builder.not_valid_before(datetime.datetime.utcnow()) cert_builder = cert_builder.not_valid_after(datetime.datetime.utcnow() + timedelta(days=days)) # 添加基础扩展(保留原代码的扩展配置) cert_builder = cert_builder.add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=False ) cert_builder = cert_builder.add_extension( x509.KeyUsage( digital_signature=True, key_encipherment=True, content_commitment=True, data_encipherment=False, key_agreement=False, key_cert_sign=False, crl_sign=False, encipher_only=False, decipher_only=False ), critical=False ) # 若需要添加config.conf中的v3_req扩展(如SubjectAltName),可手动添加示例: # cert_builder = cert_builder.add_extension( # x509.SubjectAlternativeName([x509.DNSName("example.com")]), # critical=False # ) # 用CA私钥签名证书 cert = cert_builder.sign( private_key=ca_private_key, algorithm=hashes.SHA256(), backend=default_backend() ) # 保存生成的证书 with open(output_crt_path, "wb") as f: f.write(cert.public_bytes(encoding=serialization.Encoding.PEM))
使用说明
调用示例:
# 用CA签发csr文件,生成证书 ca_sign_cert( csr_path="./csr.csr", output_crt_path="./cert.CRT", ca_crt_path="./CA.CRT", ca_key_path="./key.pem", days=365 )
补充说明
- 若CA私钥设置了密码,在加载
ca_private_key时需要添加password=b"your_password"参数 - OpenSSL的
-extfile config.conf -extensions v3_req逻辑,cryptography没有直接解析配置文件的API,需要手动添加对应扩展,代码中已给出SubjectAltName的示例
内容的提问来源于stack exchange,提问作者TheZinter
相关产品推荐
相关产品推荐

