如何使用PowerShell创建含PRINTABLE_STRING等指定编码字段的自签名证书
实现方法
直接使用New-SelfSignedCertificate无法指定DN字段的字符串编码格式,需要借助Windows的CertEnroll COM对象手动构建证书请求并生成证书,以此精准控制字段的编码类型。以下是具体步骤:
1. 通过CertEnroll COM对象生成指定编码的自签名证书
运行以下PowerShell脚本,我们将CN=wdac设置为PRINTABLE_STRING编码(如需IA5STRING或BMPSTRING,只需修改对应枚举值即可):
# 初始化CertEnroll核心对象 $enroll = New-Object -ComObject X509Enrollment.CX509Enrollment $certReq = New-Object -ComObject X509Enrollment.CX509CertificateRequestCertificate # 配置私钥参数(匹配需求的RSA 4096位) $privateKey = New-Object -ComObject X509Enrollment.CX509PrivateKey $privateKey.ProviderName = "Microsoft RSA SChannel Cryptographic Provider" $privateKey.KeySpec = [X509Enrollment.X509KeySpec]::XCN_AT_KEYEXCHANGE $privateKey.KeyLength = 4096 $privateKey.MachineContext = $false # 对应CurrentUser证书存储 $privateKey.ExportPolicy = [X509Enrollment.X509PrivateKeyExportFlags]::XCN_NCRYPT_ALLOW_EXPORT_FLAG $privateKey.Create() # 构建Subject/Issuer并指定编码为PRINTABLE_STRING $distinguishedName = New-Object -ComObject X509Enrollment.CX500DistinguishedName # 枚举值说明:XCN_CERT_NAME_STR_PRINTABLE=PRINTABLE_STRING,XCN_CERT_NAME_STR_IA5=IA5STRING,XCN_CERT_NAME_STR_BMP=BMPSTRING $distinguishedName.Encode("CN=wdac", [X509Enrollment.X509NameFlags]::XCN_CERT_NAME_STR_PRINTABLE) # 配置证书基础属性 $certReq.InitializeFromPrivateKey([X509Enrollment.X509CertificateEnrollmentContext]::ContextUser, $privateKey, "") $certReq.Subject = $distinguishedName $certReq.Issuer = $distinguishedName # 自签名证书,Issuer与Subject一致 $certReq.NotBefore = Get-Date $certReq.NotAfter = (Get-Date).AddYears(5) # 有效期设为5年,可按需调整 # 设置SHA512哈希算法 $hashOid = New-Object -ComObject X509Enrollment.CObjectId $hashOid.InitializeFromValue([X509Enrollment.ObjectId]::XCN_OID_SHA512) $certReq.HashAlgorithm = $hashOid # 添加代码签名扩展(满足WDAC规则要求) $codeSignOid = New-Object -ComObject X509Enrollment.CObjectId $codeSignOid.InitializeFromValue([X509Enrollment.ObjectId]::XCN_OID_CODE_SIGNING) $ekuExtension = New-Object -ComObject X509Enrollment.CX509ExtensionEnhancedKeyUsage $ekuExtension.InitializeEncode($codeSignOid) $certReq.X509Extensions.Add($ekuExtension) # 生成并安装证书到CurrentUser\My存储 $enroll.InitializeFromRequest($certReq) $certBase64 = $enroll.CreateRequest([X509Enrollment.EnrollmentRequestFlags]::XCN_CERTREQ_INCLUDE_CHAIN) $enroll.InstallResponse([X509Enrollment.InstallResponseRestrictionFlags]::XCN_CERT_INSTALL_RESPONSE_ALLOW_UNTRUSTED_CA, $certBase64, [X509Enrollment.EncodingType]::XCN_CRYPT_STRING_BASE64, "")
2. 验证编码是否符合要求
用certutil工具导出并查看证书字段编码:
# 定位目标证书 $targetCert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Subject -eq "CN=wdac"} # 导出为DER格式证书文件 Export-Certificate -Cert $targetCert -FilePath "C:\temp\wdac-cert.cer" -Type CERT # 查看证书详情,检查编码类型 certutil -dump "C:\temp\wdac-cert.cer"
在输出的Subject或Issuer区域,会明确显示PRINTABLE_STRING(或你指定的编码类型),而非UTF-8对应的UTF8String。
关键注意事项
- 自签名证书的
Subject与Issuer编码需保持一致,脚本中通过复用同一个CX500DistinguishedName对象实现这一点。 - 若需切换编码,直接替换
XCN_CERT_NAME_STR_PRINTABLE为对应枚举值即可:IA5STRING用XCN_CERT_NAME_STR_IA5,BMPSTRING用XCN_CERT_NAME_STR_BMP。 - 脚本中配置的密钥规格、哈希算法、代码签名扩展均符合WDAC签名证书的要求,可根据实际场景调整有效期等参数。
内容的提问来源于stack exchange,提问作者user20682592
相关产品推荐
相关产品推荐

