如何用Python cryptography模块实现带ext、config参数的openssl ca命令
使用cryptography实现openssl ca命令签名功能
核心原理说明
openssl的ca命令本质是用CA根/中间证书的私钥对CSR进行签名,生成符合CA规则的终端实体证书,cryptography没有单独的CA功能模块,相关能力全部封装在cryptography.x509模块中,无需额外依赖。
注意:cryptography没有内置解析openssl格式的.cnf配置文件、.ext扩展文件的接口,需要你提前把配置中定义的签名规则、证书扩展项提取出来,通过代码显式配置;-batch参数对应非交互签名,代码逻辑本身无交互,无需额外适配。
完整实现步骤
依赖安装
pip install cryptography
代码实现
以下代码对应你给出的openssl命令的所有参数逻辑:
from datetime import datetime, timedelta from cryptography import x509 from cryptography.x509.oid import NameOID from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import padding # -------------------------- 对应命令参数配置开始 -------------------------- # 对应 -startdate $start_date:生效时间,示例为当前时间,可自定义 not_valid_before = datetime.utcnow() # 对应 -days $duration:有效期 duration = 365 not_valid_after = not_valid_before + timedelta(days=duration) # 对应 -md sha256:签名哈希算法 signature_hash_algorithm = hashes.SHA256() # 对应 -cert $signing_ca:CA证书路径 ca_cert_path = "signing_ca.pem" # 对应 -key $pk:CA私钥路径,如果私钥有密码,加password参数传入 ca_private_key_path = "ca_private_key.pem" # 对应 -in $csr:待签名的CSR路径 csr_path = "request.csr" # 对应 -out $cert:输出证书路径 output_cert_path = "signed_cert.pem" # -------------------------- 对应命令参数配置结束 -------------------------- # 1. 加载CA证书 with open(ca_cert_path, "rb") as f: ca_cert = x509.load_pem_x509_certificate(f.read()) # 2. 加载CA私钥 with open(ca_private_key_path, "rb") as f: ca_private_key = serialization.load_pem_private_key( f.read(), password=None # 若私钥加密,传入bytes类型的密码,比如b"your_password" ) # 3. 加载CSR并校验签名 with open(csr_path, "rb") as f: csr = x509.load_pem_x509_csr(f.read()) if not csr.is_signature_valid: raise ValueError("CSR签名无效,拒绝签名") # 4. 构造证书主体,默认使用CSR的主体,可根据openssl.cnf的规则修改 subject = csr.subject # 生成证书序列号,随机生成即可,对应openssl ca的序列号分配逻辑 serial_number = x509.random_serial_number() # 5. 配置证书扩展,对应-extfile my_extfile.ext的内容 # 示例为常用扩展,需和你的ext文件内容一一对应 cert = x509.CertificateBuilder().subject_name( subject ).issuer_name( ca_cert.subject ).public_key( csr.public_key() ).serial_number( serial_number ).not_valid_before( not_valid_before ).not_valid_after( not_valid_after # 下面逐个添加扩展项,和你的ext文件内容对应 ).add_extension( x509.SubjectAlternativeName([x509.DNSName("example.com")]), critical=False, ).add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True, ).add_extension( x509.KeyUsage( digital_signature=True, content_commitment=False, key_encipherment=True, data_encipherment=False, key_agreement=False, key_cert_sign=False, crl_sign=False, encipher_only=False, decipher_only=False ), critical=True, ).add_extension( x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH]), critical=False, # 用CA私钥签名 ).sign( private_key=ca_private_key, algorithm=signature_hash_algorithm ) # 6. 导出签名后的证书 with open(output_cert_path, "wb") as f: f.write(cert.public_bytes(encoding=serialization.Encoding.PEM))
常见参数对应说明
- 你可以修改扩展项的配置,完全匹配你
.ext文件中的所有规则 - 如果你的openssl.cnf中配置了主体DN的重写规则、CRL分发点、OCSP地址等信息,直接在扩展项部分添加对应的配置即可
- 如果需要批量签名证书,只需要循环处理CSR,复用加载好的CA证书和私钥即可
内容的提问来源于stack exchange,提问作者matt_platts
相关产品推荐
相关产品推荐

