Sign CLI
本项目旨在通过使用基于云的硬件安全模块(HSM)保护的密钥,简化将安全代码签名集成到 CI 流水线中的过程。本项目是 .NET Foundation 的一部分,并遵循其 行为准则。它采用 MIT(一个 OSI 批准的许可证)授权。
您可以在 NuGet.org 上找到 Sign CLI 的最新版本。
先决条件
- 当前处于 主流支持 阶段的最新 x64 版本 Windows
- .NET 8 SDK 或更高版本
- Microsoft Visual C++ 14 运行时
安装
要在当前目录中安装 Sign CLI,请打开命令提示符并执行:
dotnet tool install --tool-path . --prerelease sign
要运行 Sign CLI,请从同一目录执行 sign。
设计
给定一个初始文件路径或 glob 模式,该工具会递归搜索目录和容器,以查找可签名文件和容器。 对于每个可签名工件,该工具使用 System.Security.Cryptography.RSA 的实现,将签名操作委托给 Azure Key Vault。 该工具计算待签名内容的摘要(或哈希值),并将摘要 --- 而非原始内容 --- 提交给 Azure Key Vault 进行摘要签名。 然后,返回的原始签名值将被整合到适合该文件类型的签名格式中。 可签名内容不会发送到 Azure Key Vault。
虽然当前版本仅限于 RSA 和 Azure Key Vault,但未来支持 ECDSA 和其他云提供商是理想的。
支持的文件类型
.msi、.msp、.msm、.cab、.dll、.exe、.appx、.appxbundle、.msix、.msixbundle、.sys、.vxd、.ps1、.psm1以及任何便携式可执行文件(PE)文件(通过 AzureSignTool).vsix- ClickOnce
.application和.vsto(通过Mage)。 见下文说明。 .nupkg
ClickOnce
签名 ClickOnce 包有几种可能性。
通常,您希望签署整个包及其所有内容,即部署清单(.application 或 .vsto)、
应用清单(.exe.manifest 或 .dll.manifest)以及底层的 .exe 和 .dll 文件本身。
为此,请确保包的所有内容均可用(即来自您构建的整个 publish 文件夹),并将
部署清单作为要签署的文件传入 - 其余文件将被自动检测并按正确顺序签署。
您也可以仅重新签署部署清单,例如,如果您想更改 Deployment URL 但保持其余内容 不变。为此,请像上述情况一样将部署清单作为要签署的文件传入,但只需确保其余文件 不存在于磁盘上。该工具将检测到它们缺失,并仅更新部署清单上的签名。 请注意,这严格用于重新签署已签署的部署清单 - 您不能拥有一个指向未签署应用清单的已签署部署清单。您还必须注意使用相同的证书签署所有清单,否则应用 将无法安装。
您还应该使用 filter 参数配合要签署的文件列表,如下所示:
**/ProjectAddIn1.*
**/setup.exe
最佳实践
- 创建一个具有最小权限的 ServicePrincipal。请注意,您无需为此身份分配任何订阅级角色。仅需访问 Key Vault 即可。
- 遵循使用 Azure Key Vault 的最佳实践。代码签名证书需要 Premium SKU 以满足密钥存储要求。
- 如果使用 Azure 基于角色的访问控制 (RBAC),将您的签名账户配置为具有以下角色:
- Key Vault Reader
- Key Vault Crypto User
- 如果使用 Azure Key Vault 访问策略,为签名账户配置访问策略 以拥有最小权限:
- Key permissions
- Cryptographic Operations
- Sign
- Key Management Operations
- Get (注意: 这仅针对公钥,而非私钥。)
- Cryptographic Operations
- Certificate permissions
- Certificate Management Operations
- Get
- Certificate Management Operations
- Key permissions
- 如果使用 Azure 基于角色的访问控制 (RBAC),将您的签名账户配置为具有以下角色:
- 在构建管道的独立阶段中隔离签名操作。
- 确保此 CLI 以及所有输入和输出文件都位于您控制的目录中。
- 以标准用户身份执行此 CLI。 无需提升权限。
- 使用从您的 GitHub Action 到 Azure 的 OIDC 身份验证。
Sample Workflows
代码签名是一个复杂的过程,可能涉及多种签名格式和工件类型。某些工件是容器,其中包含其他可签名的文件类型。例如,NuGet 包(.nupkg)通常包含 .dll 文件。签名工具将从内到外对内部所有文件进行签名,从最内层的文件开始,然后是外部文件,确保所有文件都按正确的顺序进行签名。
目前,仅能在 Windows 上对 .exe/.dll 文件及其他 Authenticode 文件类型进行签名。推荐的解决方案是在一个代理上构建,在另一个代理上使用作业或阶段进行签名,其中签名步骤在 Windows 上运行。在单独的阶段运行代码签名,以确保机密信息不会暴露给构建阶段。
构建变量
签名构建需要以下信息:
Tenant IdAzure AD 租户Client Id/Application IdServicePrincipal 标识符Key Vault Url密钥保管库的 Url。对于 EV 代码签名证书以及 2023 年 6 月之后颁发的所有证书,必须是 Premium SkuCertificate Id密钥保管库中证书的 Id。Client Secret用于 Azure DevOps PipelinesSubscription Id用于 GitHub Actions
在 Azure Key Vault 中创建代码签名证书
代码签名证书必须使用 RSA-HSM 密钥类型,以确保私钥以符合 FIPS 140-2 标准的方式存储。虽然您可以从 PFX 文件导入证书,但如果有条件,最安全的选项是创建一个新的证书签名请求(Certificate Signing Request)并提供给您的证书颁发机构,然后合并他们签发的公钥证书。详细步骤可在此处](https://learn.microsoft.com/answers/questions/732422/ev-code-signing-with-azure-keyvault-and-azure-pipe)查看。
从旧版代码签名服务迁移
如果您一直使用旧版代码签名服务,并使用 SignClient.exe 上传文件进行签名,您可以使用现有的证书和 Key Vault 配合此新工具。您需要创建一个新的 ServicePrincipal 并按照上述说明为其分配权限。
常见问题
支持哪些签名算法?
目前,仅支持 RSA PKCS #1 v1.5。
不支持 ECDSA。不仅某些签名提供商不支持 ECDSA,微软受信任根计划也不支持 ECDSA 代码签名。
请注意:使用椭圆曲线密码学(ECC)(例如 ECDSA)的签名在 Windows 及较新的 Windows 安全功能中不受支持。使用这些算法和证书的用户将面临各种错误和潜在的安全风险。由于这种已知的不兼容性和风险,微软受信任根计划建议不要向订阅者颁发 ECC/ECDSA 证书。
有用链接
- Sign CLI 入门指南(面向维护者:密码学术语、签名格式细节)
- 问题分诊策略
