winapp CLI 使本地Windows开发变得非常简单:它可以生成签名证书,在计算机上信任它,并为你启用开发人员模式。 每个步骤都会更改计算机状态或创建一个包含私钥的文件,因此它有助于确切地了解它们执行的操作。
本页说明了每条命令的后果、如何撤销它,以及在发布时应该采取哪些不同的做法。 开发证书和开发人员模式是本地测试的正常、受支持的路径, 此处的目标是了解你选择的内容,而不是避免它们。
开发证书
必须先对 MSIX 包进行签名,然后Windows才能安装它们。 在本地测试时,winapp cert generate 会创建一个自签名证书,这样你无需购买任何东西即可为自己的包签名并安装。
winapp cert generate 创建的内容
生成的证书是自签名的端到端代码签名证书:
| 财产 | 值 |
|---|---|
| Key | RSA 2048 位,标记为可导出 |
| 签名算法 | SHA-256 与 RSA (PKCS#1 v1.5) |
| 密钥用法 | 数字签名 |
| 增强型密钥用法 | 代码签名 (1.3.6.1.5.5.7.3.3) |
| 基本约束 | 不是证书颁发机构 |
| 有效性 | 默认情况下为 365 天(--valid-days) |
| Subject | 必须与清单文件中的 Publisher 匹配 |
该命令写入两项内容:
-
devcert.pfx在当前目录中(或传递给--output的路径)。 此文件同时包含证书及其私钥。 - 个人证书存储区中的证书副本(
Cert:\CurrentUser\My)。
使用 --export-cer时,它还将文件 .cer 写入到该文件 .pfx旁边。 该文件仅包含公钥证书——不含私钥——因此很适合交给团队成员,或交给需要信任你的构建产物的测试机器。
注释
在有人明确信任证书之前,没有人信任自签名证书。 它适用于自己的计算机和你自己的测试计算机;分发应用时,它不能替代真正的代码签名标识。
默认密码
winapp cert generate 使用 --password 作为 PFX 密码,除非你传递了 password。 当你稍后将该证书提供给 --password 时,同样的默认值也适用;其密码选项同样为 winapp pack。对于 --cert-password 也是如此,它接受 winapp sign。
众所周知的密码意味着私钥 devcert.pfx 实际上不受保护, 任何获取该文件的人都可以使用它对代码进行签名。 对于仅用于给你自己机器上的本地测试构建签名的一次性证书来说,这种权衡是可以接受的,这也是之所以会有这一默认设置的原因。
Important
将默认密码视为证书可释放的信号。 如果证书曾经用于对另一个人安装的内容进行签名,则它不应是 winapp cert generate 具有默认密码的证书, 请参阅 “为生产签名”。
脚本和代理无需自行比对密码:当默认值生效时,winapp cert generate --json 会报告 "defaultPasswordIsPublic": true,并在 warnings 数组中重复该披露信息。 请参阅 证书生成 JSON 输出。
证书文件所在的位置
devcert.pfx 是磁盘上的私钥。 两个规则使它摆脱了麻烦:
不要提交它。winapp cert generate 自动将证书的文件名追加到 .gitignore 它的旁边,因此已涵盖默认流。 如果移动文件、重命名文件或将其生成到由其他 .gitignore管理的目录中,请检查其后面的条目:
git check-ignore -v devcert.pfx
如果没有输出任何内容,则该文件未被忽略——请在提交前先添加该文件。
不要打包它。winapp pack 会打包输入目录中的所有内容,因此,位于应用输出文件夹中的 devcert.pfx 最终会被打进交付的 MSIX 包中。 按照 打包 EXE/CLI 指南 所示,在你要打包的文件夹之外生成证书,并在分发之前确认该文件夹中没有该证书:
# Unpack the package and check that no certificate is inside
winapp tool makeappx unpack /p .\MyApp.msix /d .\inspect /o
Get-ChildItem .\inspect -Recurse -Include *.pfx, *.cer
Tip
如果带有真实私钥的 .pfx 确实被提交或发布了,请立即进行轮换:生成新证书、重新签名,并按照 删除受信任的证书 中的步骤停止信任旧证书。 从以后的提交中删除文件不会将其从历史记录中删除。
winapp cert install 授予的权限
winapp cert install 将证书添加到存储区 LocalMachine\TrustedPeople 。 这需要管理员权限,因为它会更改计算机上每个用户的信任。
证书位于TrustedPeople中后,Windows 会将由该证书签名的任何 MSIX 包都视为受信任到足以安装,而不只是你当时测试的那个包。 对于其私钥由你持有并保存在本地的证书,这恰恰是预期的结果。 这也是为什么要慎重对待此事:
- 信任你自己生成的证书,或者来自你将在计算机上安装软件的人。
- 不要在其他人依赖的共享、生产或生成计算机上安装开发证书。
- 当同事需要安装你的测试包时,优先分发
.cer(仅公钥),而不是.pfx。 他们可以信任你的构建产物,而无须获得以你的身份签名的能力。
若要在另一台测试计算机上信任.cer,请直接在该机器上运行winapp cert install——该命令既接受.cer,也接受仅包含公钥的.pfx:
# Run as Administrator
winapp cert install .\devcert.cer
仅使用内置Windows工具的等效项是:
# Run as Administrator
Import-Certificate -FilePath .\devcert.cer -CertStoreLocation Cert:\LocalMachine\TrustedPeople
删除受信任的证书
默认情况下,开发证书会在一年后过期,但过期并不意味着证书会被移除。 当你不再需要某个证书时——例如项目已结束、机器被改作他用,或者密钥可能已经泄露——请明确将其删除。
首先,找到其指纹:
Get-ChildItem Cert:\LocalMachine\TrustedPeople |
Where-Object { $_.Subject -like '*CN=Contoso*' } |
Format-List Subject, Thumbprint, NotAfter
然后将其从计算机信任存储中删除。 此步骤需要提升权限:
# Run as Administrator. Replace with the thumbprint from the previous command.
$thumbprint = 'ABCD...'
Remove-Item -Path "Cert:\LocalMachine\TrustedPeople\$thumbprint"
cert generate 还将该证书及其私钥放入你的个人存储区。 在一个 普通、非提升权限的命令提示符中,以运行了 cert generate 的帐户身份登录,然后移除该项:
$thumbprint = 'ABCD...'
Remove-Item -Path "Cert:\CurrentUser\My\$thumbprint"
Important
在显示的上下文中运行上述两个命令。 如果你是使用其他管理员账户以提升的权限运行的,那么在该提升权限会话中,Cert:\CurrentUser 指的是该管理员的证书存储,而不是你的,因此私钥会保留在生成该密钥的用户的证书存储中。
最后,删除你分发出去的 .pfx 以及任何 .cer 副本,并取消注册你用它旁加载的包:
winapp unregister
注释
删除证书不会卸载已安装的包。 请分别通过“设置”>“应用”>“已安装的应用”卸载这些项,或对以开发模式注册的软件包使用winapp unregister。
开发人员模式
Windows 需要启用开发者模式,才能直接从磁盘上的文件夹注册应用包——即松散布局——而不是安装已生成并签名的 MSIX 包。 诸如 winapp run 和 create-debug-identity 这样的命令都依赖它,没有它就会失败,而 winapp init 会提示为你启用它。
启用后会发生哪些变化
CLI 通过在 HKEY_LOCAL_MACHINE 下写入两个 DWORD 值来启用开发者模式:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock
AllowDevelopmentWithoutDevLicense = 1
AllowAllTrustedApps = 1
由于这些是系统范围的设置,CLI 会启动一个提升权限的辅助进程,而 Windows 会显示用户帐户控制提示。 如果拒绝提示,则不会更改任何内容。
实际上,这意味着计算机将:
- 直接从磁盘上的文件夹注册应用包,无需将其打包为 MSIX,也无需进行签名(
AllowDevelopmentWithoutDevLicense)。 - 只要应用包已由该计算机信任的证书签名(包括
AllowAllTrustedApps中的任何开发证书(TrustedPeople)),就可以从 Microsoft Store 外部安装应用包。
Important
开发人员模式加上受信任的开发证书是默认安装限制的故意松动。 这种组合适用于开发和测试机器。 在生产环境中的机器、自助终端和共享基础设施上,请保持将其关闭。
控制启用时间
winapp init 会在进行任何更改前先询问,而 --use-defaults 则会完全跳过询问,使开发者模式保持不变。 这使得脚本化和 CI 默认运行安全:
winapp init --use-defaults
如果希望自行管理设置,请通过 “ > 设置系统 > 为开发人员 > 开发人员模式 ”启用一次,CLI 将检测并继续操作。
将其关掉
依次进入设置 > 系统 > 开发人员选项,然后关闭开发人员模式。 这是建议的路径,因为“设置”也会清理关联的 OS 状态。 若要在随后确认注册表值,请执行以下操作:
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock' `
-Name AllowDevelopmentWithoutDevLicense, AllowAllTrustedApps
关闭开发人员模式不会删除受信任的证书或已安装的包 - 请参阅 “删除受信任的证书”。
为生产用途签名
开发证书仅对已明确表示信任该证书的用户有效。 若要分发应用,请使用Windows已信任的标识对其进行签名。
选择签名身份
Azure 受信任签名 - 云托管的签名服务。 私钥永远不会存在于你的构建计算机上,因此无需保护、泄露或手动轮换
.pfx。 使用winapp az-sign,它使用标准Azure凭据链进行身份验证,并适用于 GitHub Actions OIDC 或托管标识。winapp az-sign .\MyApp.msix来自受信任的证书颁发机构的代码签名证书 , 将其
winapp sign作为第二个位置参数传递给,并在其中输入密码--password。 然后,你负责安全地存储密钥材料;将其保存在硬件令牌、密钥保管库或 CI 提供程序的机密存储中,并且永远不会保留在存储库中。Microsoft Store - 如果你专门通过应用商店分发,它会为你签名程序包,并且无需在提交之前进行签名。
在所有情况下,证书主题都必须与你的清单中的 Publisher 值匹配,包括稀疏包。
不要将签名密钥保存在代码仓库中
证书密码属于 CI 机密存储,不在配置文件中。 从环境中读取它们,而不是对它们进行硬编码:
winapp sign .\MyApp.msix $env:SIGNING_CERT_PATH --password $env:SIGNING_CERT_PASSWORD
这同样适用于签入源代码控制的构建配置,例如 Electron Forge 配置——请参阅 Electron 打包。
winapp az-sign 彻底避免了这个问题,因为没有需要传递的密码。
发布之前
从本地测试过渡到分发的简短清单:
- 该包使用 CA 颁发的证书、Azure 受信任签名进行签名,或提交到 Microsoft Store,而不是使用
devcert.pfx。 - 打包的输出中没有
.pfx文件或.cer文件。 - 提交的文件、生成脚本或 CI 日志中未显示证书密码。
- 证书主题与清单
Publisher匹配。 - 开发证书和开发人员模式在只需 运行 应用的计算机上未启用。
报告安全问题
若要报告 winapp CLI 本身中的安全漏洞,请遵循 SECURITY.md 中的过程。 请不要通过公开的 GitHub Issue 提交安全问题报告。