MSIX 自签名代码签名证书实用指南
2026-06-02
Tags: Windows · Microsoft Store · MSIX · 商店踩坑
在上一篇文章中,我们梳理了 MSIX 提审前的完整测试流程。其中反复出现的一个步骤就是处理自签名证书——将其安装到受信任人、用正确的证书打包等等。但那篇文章跳过一个重要问题:到底怎么创建自签名证书?
本指南涵盖了 MSIX 打包中自签名代码签名证书的所有知识点:如何创建、如何导出、如何在 Visual Studio 中使用,以及如何在团队中管理。
为什么 MSIX 需要签名
MSIX 包在安装之前必须经过数字签名。这不是可选项——即使是旁加载和本地测试,操作系统也要求每个 .msix 文件拥有有效签名。
对于 Store 分发,微软在认证通过后会用自己的证书为你的包签名。但对于本地测试和旁加载,你需要自己的证书。这时自签名证书就派上用场了:让你无需购买商业代码签名证书,也能为开发和测试用的包签名。
签名过程有两个目的:
- 完整性:确保包在签名后未被篡改
- 身份标识:标识发布者(你)——证书中的 CN(Common Name)必须与
Package.appxmanifest中的<Publisher>值一致
使用 New-SelfSignedCertificate
Windows 提供了 New-SelfSignedCertificate PowerShell cmdlet,可用于生成测试用途的证书。以管理员身份打开 PowerShell 并尝试以下命令:
New-SelfSignedCertificate -Type Custom -Subject "CN=YourCompany" -KeyUsage DigitalSignature -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") -CertStoreLocation "Cert:\CurrentUser\My"我们来逐一拆解每个参数:
| 参数 | 作用 |
|---|---|
-Type Custom | 创建自定义证书而非基础证书 |
-Subject "CN=YourCompany" | 设置 Common Name——应与你的应用在 Package.appxmanifest 中的 Publisher 一致 |
-KeyUsage DigitalSignature | 将证书标记为数字签名用途 |
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") | 扩展密钥用法设置为代码签名(1.3.6.1.5.5.7.3.3),外加基本约束设置为终端实体(2.5.29.19)——Windows 部署引擎对应用包有此要求 |
-CertStoreLocation "Cert:\CurrentUser\My" | 将证书存储在当前用户的个人证书存储中 |
如果缺少这两个 TextExtension 值中的任意一个,证书可能无法被完全识别——基本约束 OID 将其标记为终端实体(非 CA),Windows 部署引擎在验证 MSIX 包时会检查这一点。缺少它可能导致部署错误,或在某些 Windows 版本上触发 WACK 警告。
注:在我自己的项目中,一直使用不带基本约束的自签名证书,也没有出现过问题。该约束是微软推荐的最佳实践,但并非开发和旁加载场景的硬性要求。
创建带代码签名 EKU 的证书
如果你已经创建了一个不带代码签名 EKU 的证书,仍可以验证它是否具备正确的属性。打开证书(通过 certlm.msc)并检查详细信息 → 增强型密钥用法——应该能看到列出了代码签名。
以下是一个实用的脚本,用于创建证书并将其准备好供 MSIX 使用:
# 创建自签名代码签名证书(代码签名 EKU + 基本约束)
$cert = New-SelfSignedCertificate -Type Custom -Subject "CN=YourCompany" -KeyUsage DigitalSignature -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") -CertStoreLocation "Cert:\CurrentUser\My"
# 显示证书详情
$cert | Format-List Subject, Thumbprint, NotAfter
# 输出指纹以便参考
Write-Host "Certificate thumbprint: $($cert.Thumbprint)"将 "CN=YourCompany" 替换为你实际的发布者名称。你可以在 Package.appxmanifest 的 Identity 元素中找到发布者名称:
<Identity Name="YourApp" Publisher="CN=YourCompany" Version="1.0.0.0" />导出 PFX 与 CER 的区别
创建证书后,通常需要两种类型的文件:
PFX(个人信息交换格式)
包含私钥 + 证书。Visual Studio 使用它来签名包。请像对待密码一样保护它——任何拥有 PFX 的人都可以以你的身份签名包。
$password = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath "codesign.pfx" -Password $passwordCER(证书文件)
仅包含公钥证书(不含私钥)。将其分发给测试机器,以便它们信任你签名的包。
Export-Certificate -Cert $cert -FilePath "codesign.cer"快速参考
| 格式 | 包含私钥? | 用途 |
|---|---|---|
.pfx | 是 | 签名包(Visual Studio、signtool) |
.cer | 否 | 安装在测试机器上以建立信任 |
导入证书并查看指纹
要在测试机器上安装使用自签名证书签名的 MSIX 包,该证书必须被系统信任。
安装证书
- 双击
.cer文件 → 安装证书 - 选择 本地计算机 → 下一步
- 选择 将所有的证书都放入下列存储 → 浏览 → 选择 受信任人
- 完成向导
或者通过 PowerShell:
Import-Certificate -FilePath "codesign.cer" -CertStoreLocation "Cert:\LocalMachine\TrustedPeople"查看指纹
使用命令行签名工具时需要用到指纹:
# 列出个人存储中所有代码签名证书
Get-ChildItem -Path "Cert:\CurrentUser\My" -CodeSigningCert | Format-Table Subject, Thumbprint, NotAfter指纹是一个 40 字符的十六进制字符串。请准确复制——签名命令中会用到它。
在 Visual Studio 中使用证书
有了 PFX 文件后,就可以在 Visual Studio 的打包向导中使用它:
- 右键项目 → 打包和发布 → 创建应用程序包
- 选择 旁加载 → 在签名方法中选择 从文件选择...
- 浏览到你的
.pfx文件并输入密码 - 完成打包向导
证书保存在打包配置文件中,因此无需每次都重新选择。但如果证书过期或更换了新证书,则需要更新配置文件。
从证书存储中选择证书
如果你已将 PFX 导入到个人证书存储中,也可以直接选择:
- 在签名步骤中,展开下拉菜单(不要点击 "从文件选择...")
- 在列表中查找你的证书(通过你指定的 CN 来识别)
- 选择它并继续
这种方式很方便,但要注意——Visual Studio 可能会缓存特定的指纹,如果证书被续期(生成新的密钥对),存储的引用可能会失效。
证书过期、续期与重新签名
使用 New-SelfSignedCertificate 创建的自签名证书默认有效期为 1 年(某些版本默认为 3 年——请检查 NotAfter 属性)。
检查清单
- [ ] 记录证书的过期日期
- [ ] 在过期前创建新证书并重新签名所有包
- [ ] 将新的
.cer分发给测试机器 - [ ] 更新 Visual Studio 中的打包配置文件
- [ ] 对于 Store 提交,使用新证书生成新的 Test 包
检查过期时间:
Get-ChildItem -Path "Cert:\CurrentUser\My" -CodeSigningCert | Format-Table Subject, NotAfter续期时,使用相同的 CN 创建新证书,导出新的 PFX/CER,然后重新签名你的包。指纹会改变,所以请确保更新所有引用。
团队开发建议
当多个开发者需要使用同一证书签名包时:
- 将 PFX 存放在安全共享位置——比如团队存储中的密码保护归档,或支持文件附件的密码管理器
- 切勿将 PFX 提交到源代码管理——将
*.pfx添加到.gitignore - 在团队的密码管理器(而非代码或文档)中记录密码
- 每位开发者将 PFX 导入到各自的个人证书存储,然后在 Visual Studio 中选择
- 如果需要为每位开发者创建单独的证书(用于非发布构建),请使用相同的 CN
对于 CI/CD 流水线,大多数构建代理支持通过安全环境变量或密钥导入 PFX——请查阅你的 CI 平台文档以了解推荐做法。
本文属于商店踩坑系列的延伸阅读。