Impeccable Windows 引擎二进制如何做 Authenticode 签名?
2026/9/10 14:43:27 网站建设 项目流程

Impeccable Windows 引擎二进制如何做 Authenticode 签名?

【免费下载链接】impeccableThe design language that makes your AI harness better at design.项目地址: https://gitcode.com/GitHub_Trending/im/impeccable

当 impeccable 的引擎(engine)发布新版本时,Windows x64 产物impeccable.exe不能以未签名状态直接发布。项目用 Azure Artifact Signing 对二进制做 Authenticode 签名,签发方为Renaissance Geek, Inc.,签名必须在计算发布校验和之前完成。整条路径由bun run release:engine触发、在 GitHub Actions 的release-engine工作流中执行,本文说明这条路径上每一步做了什么、哪些权限是前提、以及如何确认签名有效。

完整依据见 Windows engine signing 与 release-engine 工作流。

前置条件:签名身份与访问边界

签名不是本地能完成的动作,它依赖一组预先配置好的 Azure 与 GitHub 资源。发布前需要确认以下条件都已存在(详见 docs/WINDOWS-SIGNING.md):

  • Azure 账号impeccable-signing,East US 端点;Public Trust 证书配置文件impeccable-windows
  • 用户指定的托管身份impeccable-release-signing,与账号在同一资源组。它在 Azure 中唯一拥有的角色是Artifact Signing Certificate Profile Signer,且只限定在impeccable-signing/certificateProfiles/impeccable-windows,不覆盖整个账号或订阅。
  • 联合凭据github-windows-signing:issuer 为https://token.actions.githubusercontent.com,audience 为api://AzureADTokenExchange,subject 为repo:pbakaus/impeccable:environment:windows-signing
  • GitHub 环境windows-signing:仅对匹配engine-v*tag开放,pbakaus是必需审批人,且管理员旁路(administrator bypass)关闭。
  • GitHub 环境变量AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_SUBSCRIPTION_ID,它们存放的是公开标识符而非密钥。GitHub 上不存任何客户端密钥、私钥或 PFX。

执行路径:从打 tag 到签名产物

1. 触发引擎发布

在仓库根目录运行:

bun run release:engine

该命令对应node scripts/release.mjs engine,只负责本地校验与打 tag:它检查ENGINE_VERSION、npm platform-package 的版本 pin 和工作区是否干净,然后推送engine-v<ENGINE_VERSION>tag。构建、签名、发布全部由 CI 完成,维护者本机不需要五个平台的目标工具链。脚本也支持--dry-run,只做前置检查不推 tag。

2. build job:产出未签名 Windows 二进制

tag 匹配engine-v*后,.github/workflows/release-engine.yml 被触发。buildjob 的 matrix 构建五个目标(darwin-arm64 / darwin-x64 / linux-x64 / linux-arm64 / windows-x64),并先校验 tag 与ENGINE_VERSION一致。

Windows 构建的产物被刻意命名为unsigned-windows-x64artifact——这个名字不以impeccable-开头,是后面 publish job 收集模式(impeccable-*)无法误收它的关键设计。

3. sign-windows job:签名与验证

这是唯一拿到id-token: write(OIDC)权限的 job,绑定windows-signing环境,因此需要人工审批。审批前要检查该 tag 的 commit 与工作流内容:环境审批一旦通过,这个 job 就获得了以公司名义签名的能力。

job 的步骤顺序是固定的:

  1. actions/download-artifact同一次运行下载unsigned-windows-x64。job 不 checkout 仓库代码,也不执行下载来的引擎。
  2. azure/login以 OIDC 方式登录 Azure,使用上面三个环境变量中的公开标识符。
  3. azure/artifact-signing-action(pin 到 commit SHA)执行签名,关键配置:
uses: azure/artifact-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 # v2 with: endpoint: https://eus.codesigning.azure.net/ signing-account-name: impeccable-signing certificate-profile-name: impeccable-windows files: ${{ github.workspace }}\unsigned\impeccable.exe file-digest: SHA256 timestamp-rfc3161: http://timestamp.acs.microsoft.com timestamp-digest: SHA256 description: Impeccable engine description-url: https://impeccable.style exclude-environment-credential: true exclude-azure-cli-credential: false cache-dependencies: false

签的恰好是impeccable.exe一个文件;RFC 3161 时间戳是必需的,因为 Azure 签发的是短生命周期签名证书。 4. 签名后、上传前,用 PowerShell 验证:

$ErrorActionPreference = 'Stop' $signature = Get-AuthenticodeSignature -LiteralPath 'unsigned/impeccable.exe' if ($signature.Status -ne 'Valid') { throw "Invalid Windows signature: $($signature.Status) — $($signature.StatusMessage)" } $publisher = $signature.SignerCertificate.GetNameInfo([System.Security.Cryptography.X509Certificates.X509NameType]::SimpleName, $false) if ($publisher -cne 'Renaissance Geek, Inc.') { throw "Unexpected Windows publisher: $publisher" } if ($null -eq $signature.TimeStamperCertificate) { throw 'The Windows signature has no timestamp.' } Write-Output "Verified publisher: $publisher; certificate: $($signature.SignerCertificate.Thumbprint)"

验证同时检查三件事:签名状态为Valid、发布者名恰为Renaissance Geek, Inc.、时间戳证书存在。任何一项失败该步直接抛错,job 中没有任何continue-on-error。 5. 验证通过后才把产物以impeccable-windows-x64的名字上传,publish job 只收集得到带签名的版本。

4. publish job:等待签名后发布

publishjob 的needs[build, sign-windows],且只下载匹配impeccable-*的 artifact——未签名的中间产物unsigned-windows-x64在名字层面就进不来。它为每个二进制生成.sha256侧车文件(此时计算,因此校验和对应的是已签名字节),再用gh release create发布;不带--clobber,已发布的 release 资产不可变。

结果验证

  • 运行内验证:sign-windows job 的 PowerShell 步骤(上文)就是签名有效性的判定条件——StatusValid、发布者正确、有时间戳,三步全过才会走到上传。
  • 工作流回归测试bun test tests/release-engine-workflow.test.js对 tests/release-engine-workflow.test.js 解析的 YAML 做断言:只有 sign-windows 拿到id-token: write、签名参数(证书配置、RFC 3161 时间戳、SHA256 digest)、验证步骤必须位于签名之后上传之前、publish 的下载模式收集不到未签名 artifact、第三方 action 全部 pin 到 commit。
  • 端到端:docs/WINDOWS-SIGNING.md 明确说明,工作流配置已有回归测试覆盖,但一次真实的受保护引擎发布仍是验证 Azure OIDC 与 Authenticode 端到端流程所必需的。如果你刚配置完环境,用一次真实 tag 发布来确认是预期行为。

失败处理与边界

  • 签名或验证失败:修复原因后重试。文档明确要求不要加 unsigned 回退,也不要放宽windows-signing环境门槛。
  • 不要 pin 叶子证书 thumbprint:Azure 会轮换它,pin 住会导致后续签名失败。
  • 已发布资产不可替换:不能用签名字节替换同版本已发布的未签名二进制;修复方式是发新版本。
  • 与 skill 包签名区分开impeccable install校验的 Ed25519 远程 skill ZIP 签名(docs/BUNDLE-SIGNING.md)是另一套机制,保护的是 skill bundle 下载,不认证引擎二进制;引擎二进制的完整性目前靠发布时的 SHA-256 侧车加上 Windows 平台的 Authenticode 签名。
  • 权限面:只有 sign-windows job 拿到 OIDC token,只有 publish job 能写 release;sign job 不 checkout 代码,Azure 身份下不会执行仓库代码。

下一步

配置完成并通过bun test tests/release-engine-workflow.test.js后,按 docs/ENGINE.md 的发布顺序继续:bun run release:engine发出engine-v<版本>后,npm platform packages 与 skill/CLI 发布会被scripts/check-engine-release.mjs的门禁等待这次引擎发布完成。

【免费下载链接】impeccableThe design language that makes your AI harness better at design.项目地址: https://gitcode.com/GitHub_Trending/im/impeccable

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询