如何在Windows上验证Azure Trusted Signing签名的MSI安装包
自动更新场景下Azure Trusted Signing签名验证的推荐方案
核心验证逻辑基础
Azure Trusted Signing的核心特点是证书自动轮换,因此不能依赖固定证书指纹做验证,需转向基于证书属性和链信任的验证逻辑。Get-AuthenticodeSignature是Windows原生的可靠工具,其返回的Valid状态已经包含了基础的证书链验证、根CA信任检查,但仍需补充针对性的属性校验。
必须执行的关键检查项
1. 签名状态验证
首先确保Get-AuthenticodeSignature返回的Status字段为Valid,这是最基础的验证:
- 该状态意味着证书链完整且受Windows信任(根CA在系统受信任根存储中)
- 默认包含证书吊销检查(可通过参数调整,但不建议关闭)
2. 颁发者与主题验证
Azure Trusted Signing的签名证书由微软固定的CA颁发,且主题会关联你的Trusted Signing账户/池信息:
- 颁发者通常为
CN=Microsoft Azure Code Signing PCA 2021, O=Microsoft Corporation, L=Redmond, S=Washington, C=US(可从Azure Portal的Trusted Signing配置中确认) - 主题需匹配你创建的Trusted Signing账户或签名池的标识,比如
CN=Your_Trusted_Signing_Pool_Name - 这两个值是相对固定的(除非微软更新根CA),可硬编码到验证逻辑中
3. EKU(增强型密钥用法)验证
必须确认证书包含代码签名EKU(OID: 1.3.6.1.5.5.7.3.3),防止攻击者用其他用途的微软证书伪造签名:
- 只有具备该EKU的证书,才被允许用于代码签名场景
- 通过
SignerCertificate.EnhancedKeyUsageList可获取证书的EKU列表
4. 强制证书链验证
虽然Get-AuthenticodeSignature默认会执行链验证,但程序化实现时需确保未绕过该环节:
- 若使用PowerShell,无需额外参数,
Status为Valid即代表链验证通过 - 若使用原生API(如
WinVerifyTrust),需指定正确的验证策略(WINTRUST_ACTION_GENERIC_VERIFY_V2),确保启用完整的链校验
程序化实现方案
方案1:PowerShell脚本集成(快速落地)
适合快速实现验证逻辑,可直接在应用中调用PowerShell脚本:
$msiPath = "C:\path\to\binary.msi" $signature = Get-AuthenticodeSignature -FilePath $msiPath # 检查签名基础状态 if ($signature.Status -ne 'Valid') { Write-Error "签名验证失败: $($signature.StatusMessage)" exit 1 } # 验证颁发者(替换为你的Trusted Signing对应的CA) $expectedIssuer = "CN=Microsoft Azure Code Signing PCA 2021, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" if ($signature.SignerCertificate.Issuer -ne $expectedIssuer) { Write-Error "颁发者不匹配: 预期[$expectedIssuer],实际[$($signature.SignerCertificate.Issuer)]" exit 1 } # 验证主题(替换为你的Trusted Signing账户/池名称) $expectedSubject = "CN=Your_Trusted_Signing_Pool_Name" if ($signature.SignerCertificate.Subject -ne $expectedSubject) { Write-Error "主题不匹配: 预期[$expectedSubject],实际[$($signature.SignerCertificate.Subject)]" exit 1 } # 验证代码签名EKU $codeSigningOid = "1.3.6.1.5.5.7.3.3" $hasValidEku = $signature.SignerCertificate.EnhancedKeyUsageList | Where-Object { $_.Oid.Value -eq $codeSigningOid } if (-not $hasValidEku) { Write-Error "证书不具备代码签名权限" exit 1 } Write-Host "MSI签名验证通过"
方案2:原生API调用(应用内集成)
若需在Rust等应用中直接实现,可调用Windows原生的WinVerifyTrust API:
- 使用
winapi或windowscrate构造WINTRUST_DATA结构,指定验证对象为MSI文件路径 - 验证策略选择
WINTRUST_ACTION_GENERIC_VERIFY_V2,确保启用完整的链验证 - 调用成功即代表签名有效,失败则返回具体错误码(如链不完整、证书吊销等)
关键注意事项
- 禁止硬编码证书指纹:Azure Trusted Signing会定期轮换证书,硬编码指纹会导致后续更新验证失败
- 保持系统根证书更新:Windows自动更新会维护受信任根证书,离线环境需手动导入微软的根CA,否则链验证会失败
- 不要关闭吊销检查:吊销检查可防止已泄露或过期的证书被滥用,仅在极端离线场景下可考虑临时关闭
内容的提问来源于stack exchange,提问作者Pinabile
相关产品推荐
相关产品推荐

