CI 里 SignTool 不写 /fd,警告和硬错误卡在哪一版?

同一条签名脚本,有的构建镜像还能绿着过,有的直接非零退出。CI 日志里 SignTool 多出一截 digest 相关输出:有的仍是警告、退出码看起来像成功,有的已经红了。证书没换,脚本参数也还是旧的。对照 Microsoft Learn 上的 SignTool 说明,问题多半出在有没有显式写出文件摘要算法和时间戳摘要算法。

Learn 页对 /fd、/td 怎么写

页面开头有一段总述:Windows SDK、Windows Hardware Lab Kit(HLK)、Windows Driver Kit(WDK)、Windows Assessment and Deployment Kit(ADK)在 builds 20236 及以后,签名时需要指定摘要算法。sign 要带文件摘要选项 /fd,做时间戳时要带时间戳摘要选项 /td。

同一段接着写:签名时不写 /fd、时间戳时不写 /td,命令起初会抛出警告,错误码为 0。在后续版本的 SignTool 里,该警告会变成错误。官方推荐使用 SHA256。页面还提到 SHA384 及更强校验需要 Windows 11,或带 2022 年 11 月更新的 Windows 10——这是系统侧能力说明,跟「缺参数算警告还是错误」是两件事。

参数表里的措辞更硬一点:/fd 一节写着,签名时如果未指定该选项,命令会生成错误。配合 /tr 使用的 /td 一节也写着,时间戳时未指定会生成错误。timestamp 子命令下的 /td 则仍写「未指定会生成警告」。同一文档里,「起初警告、后续变错误」和参数表里的「未指定即错误」并存。对照原文并列即可,不替某台 CI 镜像断定「已经全局变成硬错误」——本机 signtool 实际输出版本行为才算数,但脚本侧应主动写上参数,别赌警告还能当成功。

文档没有给出「从哪一个精确 Kits 内部版本号起,缺 /fd 一律非零退出」的对照表。能核实的只有:20236+ 起要求写明摘要,缺省行为会从警告走向错误。流水线若混用多台构建机、多份 Windows Kits,就会出现「同一条脚本有的绿有的红」。

最小参数形态

示意(路径、证书、时间戳 URL 换成你们自己的,不要把口令写进仓库):

signtool sign /f MyCert.pfx /fd SHA256 /tr http://timestamp.example.com /td SHA256 MyApp.exe

Learn 示例里也有 /a /fd SHA256、PFX 加 /fd SHA256、以及 /tr 搭配 /td SHA256 的写法。旧脚本只写了 /t 或 /tr、却漏了 /fd 和 /td,在较新的 SDK 工具链上最容易中招。CI 镜像一升级 Windows Kits,现象就会从「绿但刷警告」变成「直接红」。

排查时先看构建镜像里 signtool.exe 落在哪个 Kits 目录(页面举例形态类似 Windows Kits\10\bin\<version>\x64\signtool.exe),把 Kits 版本、完整命令行,以及「警告 / 错误」原文留进 CI 日志。警告阶段 exit 仍可能是 0,若脚本只用「非零才失败」当门槛,digest 提示会被当成噪声放过,Kits 一升级同一条命令就变红。把 /fd、/td 写进共享签名步骤(模板仓库或 Action 复合步骤),比每条流水线各自改一处更不容易漏。警告还在绿的阶段就改,比等「后续版本」变成错误再救火省事。

和选证那一层分开看

能签、签得稳,前提仍是手里有一张合法的代码签名证书,以及私钥保管、时间戳服务可不可用。证书类型、SmartScreen 还指望不指望 EV「首下即信任」、商店分发会不会由平台重签、合同里次数帽和超额怎么问清,都属于选证和分发路径问题;发布后若站内有选证帖,可再补互链。工具参数写全了,选错证或跳过时间戳照样会在用户机器上出别的麻烦。证选对了,CI 却一直省略 /fd,也会在 SDK 升级后突然挂掉。两层分开查,少把「命令行缺参数」误判成「证书买错了」。

你们流水线现在是警告还能当成功,还是缺 /fd 已经非零退出?升级 Kits 前后日志里那一行原文不妨打码贴出来对一下。