如何用Python cryptography模块生成含UPN SAN的CSR?解决DER格式错误
解决Python cryptography生成带UPN SAN的CSR时的DER编码错误
错误原因
直接将UPN字符串编码为UTF-8字节串传给x509.OtherName是错误的。UPN对应的OID(1.3.6.1.4.1.311.20.2.3)要求值必须是ASN.1 DER编码的UTF8String,原始UTF-8字节缺少ASN.1的类型标签和长度字段,导致解析时触发ShortData错误。
修正方案
使用cryptography.hazmat.primitives.asn1模块将UPN字符串转换为符合要求的DER编码字节串,再传入OtherName。同时注意CSR必须包含主题名称(多数CA强制要求)。
完整修正代码
from cryptography import x509 from cryptography.hazmat.primitives import hashes, serialization, asn1 from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat._oid import ObjectIdentifier # 生成RSA私钥 key = rsa.generate_private_key(public_exponent=65537, key_size=3072) # 保存私钥到文件 with open("rsa.key", "wb") as f: f.write(key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), )) # 将UPN字符串转换为DER编码的UTF8String upn_value = "upn@email.com" upn_der = asn1.UTF8String(upn_value).public_bytes(serialization.Encoding.DER) # 构造CSR csr_builder = x509.CertificateSigningRequestBuilder() # 添加主题名称(必填,否则多数CA会拒绝) csr_builder = csr_builder.subject_name(x509.Name([ x509.NameAttribute(x509.NameOID.COMMON_NAME, "upn-user"), ])) # 添加带UPN的SubjectAlternativeName扩展 csr_builder = csr_builder.add_extension( x509.SubjectAlternativeName([ x509.OtherName(ObjectIdentifier('1.3.6.1.4.1.311.20.2.3'), upn_der), ]), critical=False ) # 签名生成CSR csr = csr_builder.sign(key, hashes.SHA256()) # 保存CSR到文件 with open("upn_csr.pem", "wb") as f: f.write(csr.public_bytes(serialization.Encoding.PEM))
验证方法
使用OpenSSL查看生成的CSR,确认UPN已正确添加:
openssl req -in upn_csr.pem -noout -text
在输出中找到X509v3 Subject Alternative Name部分,会显示类似如下内容:
OtherName:
1.3.6.1.4.1.311.20.2.3:UTF8String:upn@email.com
内容的提问来源于stack exchange,提问作者hpr
相关产品推荐
相关产品推荐

