如何向cryptography的x509.SubjectAlternativeName传入SAN列表生成CSR
正确生成包含CN与多SAN的证书签名请求(CSR)
问题根源
你之前的错误是将字符串形式的x509.DNSName语句存入列表,而不是创建实际的x509.DNSName实例。cryptography库的扩展需要接收对应的对象实例,而非字符串代码。
正确实现代码
from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography import x509 from cryptography.x509.oid import NameOID from cryptography.hazmat.backends import default_backend def generate_csr(common_name, san_list, private_key_path=None): # 生成RSA私钥 private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend() ) # 构造证书主题(包含CN) subject = x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, common_name), # 可按需添加其他主题字段,比如组织、国家等 # x509.NameAttribute(NameOID.ORGANIZATION_NAME, "My Org"), ]) # 构造SAN扩展:创建x509.DNSName实例的列表 san_extension = x509.SubjectAlternativeName([ x509.DNSName(san) for san in san_list ]) # 构建CSR csr_builder = x509.CertificateSigningRequestBuilder().subject_name( subject ).add_extension( san_extension, critical=False # SAN扩展一般设为非关键 ) # 用私钥签名CSR csr = csr_builder.sign( private_key, x509.SignatureAlgorithmOID.SHA256_WITH_RSA_ENCRYPTION, default_backend() ) # 导出CSR为PEM格式 csr_pem = csr.public_bytes(encoding=serialization.Encoding.PEM) # 可选:保存私钥到指定路径 if private_key_path: with open(private_key_path, "wb") as f: f.write(private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() )) return csr_pem # 使用示例 if __name__ == "__main__": cn = "example.com" sans = ["www.example.com", "api.example.com", "test.example.com"] csr_pem = generate_csr(cn, sans, "private_key.pem") print(csr_pem.decode("utf-8"))
关键说明
- SAN扩展构造:必须通过
x509.DNSName(san)创建实例,再放入列表,不能直接存字符串或代码文本。 - 主题字段:除了CN,可根据需求添加组织(ORGANIZATION_NAME)、国家(COUNTRY_NAME)等其他
NameOID对应的字段。 - 签名算法:示例用SHA256-RSA,可根据需要替换为SHA384_WITH_RSA_ENCRYPTION等其他算法。
- 私钥处理:示例中可选保存私钥,实际使用时注意私钥的安全存储。
内容的提问来源于stack exchange,提问作者landy
相关产品推荐
相关产品推荐

