跳到主要内容
版本:V2.2.0

参考资料

本页面整理 sslTrus 远程代码签名服务在不同集成方式中共用的参考信息,包括:

  • 代码签名次数计算规则。
  • Authenticode 和 RFC 3161 时间戳协议。
  • 常用代码签名时间戳服务器。
  • 生产环境选择时间戳服务时需要关注的事项。

签名次数计算

签名次数按实际完成的签名动作计算。

简单理解:

一个文件成功完成一次签名 = 一次签名次数

签名次数不是按照源代码文件数量计算,也不是按照一次构建、一次打包或一次 CI/CD Pipeline 计算。

例如:

100 个源代码文件

编译生成 1 个 app.exe

app.exe 成功签名一次

1 次签名

如果一次构建产生:

app.exe
helper.dll
installer.msi

并且三个文件都分别完成签名,则:

签名次数 = 3 次

基本规则

签名次数主要看:

  1. 最终有哪些文件或对象被签名。
  2. 每个对象实际完成了多少次签名。
  3. 使用的是普通客户端签名,还是 KSP、Jarsigner 等底层签名调用方式。
  4. 构建工具是否自动签名了额外的 EXE、DLL、卸载程序或安装包。

常见签名对象包括:

  • .exe
  • .dll
  • .msi
  • .msp
  • .sys
  • .cat
  • .jar
  • 卸载程序,例如 uninstall.exe

只要某个对象实际成功完成一次签名,就按照对应的计次规则计算。

成功才计次

只有远程代码签名服务成功完成签名,才产生签名次数。

以下情况通常不计次:

  • 鉴权失败。
  • 参数错误。
  • 证书不可用。
  • 网络请求失败。
  • 服务端没有成功返回签名结果。
  • 查询证书。
  • 查询签名记录。
  • 验证签名。
  • 移除已有签名。
  • 生成验证文件。

如果远程服务已经成功返回签名结果,但客户端随后在本地写入文件、添加时间戳或执行后续处理时失败,则已经完成的远程签名仍然按照成功签名计算。

时间戳不单独计次

时间戳用于证明签名在特定时间已经存在,不属于新的代码签名操作。

因此:

代码签名       → 产生签名次数
添加时间戳 → 不额外产生签名次数
验证签名 → 不产生签名次数

时间戳服务是否成功,只影响最终签名文件的时间戳结果,不代表额外执行了一次代码签名。

SignTool CLI

使用 sslTrus SignTool CLI:

signtool sign \
--cert-code CERT_CODE \
--file app.exe

如果签名成功:

1 个文件 × 1 次成功签名 = 1 次

例如:

signtool sign --cert-code CERT_CODE --file app.exe
signtool sign --cert-code CERT_CODE --file helper.dll
signtool sign --cert-code CERT_CODE --file installer.msi

三个文件全部成功:

合计 = 3 次

SignTool CLI 双签

如果使用普通 SignTool CLI 同时启用 SHA-1 和 SHA-2:

signtool sign \
--cert-code CERT_CODE \
--file app.exe \
--sha1=true \
--sha2=true

普通 CLI 双签按照一个客户端签名任务计算:

GUI / SignTool CLI 双签 = 1 次

这是普通客户端签名流程与 KSP 底层签名调用最容易混淆的地方。

Windows KSP

KSP 是 Windows CNG Provider 集成方式。

Microsoft SignTool、MSBuild、Visual Studio、Electron 打包工具或其他 Windows 软件通过 KSP 调用远程代码签名时,计次更接近:

底层远程私钥签名调用次数

例如:

操作签名次数
app.exe 执行一次 SHA256 签名1 次
先执行 SHA256,再追加 SHA12 次
分别签名 app.exehelper.dlluninstall.exe3 次

因此:

SignTool CLI 双签 = 1 次
KSP 双签 = 2 次

如果工具对同一个文件执行多次底层签名操作,每次成功的远程签名都会分别计算。

CSP

CSP 是传统 Windows CryptoAPI Provider。

CSP 同样由 Microsoft SignTool 或其他 Windows 应用通过 Provider 调用远程签名服务。

判断签名次数时,应以实际发生的远程私钥签名操作为准。

如果工具分别对多个文件或对同一个文件执行多次签名,应分别计算。

Jarsigner

使用 sslTrusJarsigner Provider 时,标准 jarsigner 会在签名过程中调用远程代码签名服务。

通常:

操作签名次数
app.jar 签名1 次
对 3 个 JAR 分别签名3 次
对同一个 JAR 再执行一次签名再增加 1 次
jarsigner -verify0 次
生成验证用 keystore0 次

因此:

每个 JAR 每次成功完成签名 = 1 次

安装包

安装包需要区分:

  1. 安装包内部的可执行文件。
  2. 安装包本身。

例如:

app.exe       → 签名 1 次
installer.msi → 签名 1 次

则:

合计 = 2 次

如果还有其他文件:

文件是否签名签名次数
app.exe1
helper.dll1
driver.sys1
installer.msi1
合计4

安装包中包含多少源代码、资源文件、图片或配置文件不会直接影响签名次数。

关键是:

最终到底有哪些产物被实际签名

Electron

Electron Builder、Electron Forge 等桌面应用构建工具可能在一次打包过程中自动签名多个文件。

常见对象包括:

  • 主程序 .exe
  • DLL
  • 更新程序
  • 卸载程序
  • 安装包 .exe
  • MSI
  • 其他辅助可执行文件

例如:

产物签名次数
MyApp.exe1
ffmpeg.dll1
update.exe1
uninstall.exe1
MyApp Setup.exe1
合计5

因此:

一次 Electron Build ≠ 一次签名

应该根据实际签名的产物数量和每个产物执行的签名次数计算。

如果 Electron 使用 KSP,并对同一个文件执行双签,该文件还可能产生两次远程签名。

快速判断

不知道一次构建会产生多少签名次数时,可以依次确认:

1. 最终有哪些文件被签名?
2. 每个文件签了几次?
3. 使用的是 SignTool CLI 还是 KSP / Jarsigner?
4. 构建工具有没有自动签额外文件?

可以简单理解为:

签名次数 = 成功完成的签名动作数量之和

特别注意:

GUI / SignTool CLI 双签                = 1 次
KSP 对同一个文件执行两次底层签名 = 2 次
Jarsigner 每个 JAR 每次成功签名 = 1 次
时间戳 = 0 次
验证签名 = 0 次

时间戳服务器

代码签名通常会同时使用时间戳服务。

时间戳可以证明数字签名在特定时间已经存在,从而使验证方能够结合签名证书、时间戳证书、撤销状态和验证策略判断签名的有效性。

代码签名常见两种时间戳协议:

协议说明
AuthenticodeMicrosoft 传统时间戳协议,主要用于兼容旧式 Windows 代码签名流程
RFC 3161通用时间戳协议,适合现代代码签名场景

现代代码签名场景通常优先使用 RFC 3161

RFC 3161

RFC 3161 时间戳请求发送的是待时间戳数据的摘要,而不是原始文件。

基本流程:

代码签名

计算待时间戳数据摘要

发送摘要到 TSA

TSA 返回时间戳令牌

写入最终签名

时间戳令牌通常包含:

  • 数据摘要。
  • 时间戳签发时间。
  • TSA 策略。
  • TSA 数字签名。

时间戳服务器不会因为添加时间戳而额外消耗 sslTrus 代码签名次数。

常用时间戳服务器

以下端点适用于常见代码签名场景。

生产使用前,应重新确认对应提供商的最新官方文档、服务策略和可用性。

Microsoft

http://timestamp.acs.microsoft.com

主要用于 RFC 3161 时间戳。

适合作为 Windows 现代代码签名场景的时间戳候选。

示例:

--timestamp-rfc3161=http://timestamp.acs.microsoft.com

Microsoft SignTool:

/tr http://timestamp.acs.microsoft.com
/td SHA256

Sectigo

http://timestamp.sectigo.com

支持:

  • Authenticode
  • RFC 3161

可用于 Windows 和其他支持相应协议的代码签名工具。

Sectigo 对批量调用存在服务侧使用要求,生产系统应根据其当前官方策略控制调用频率。

DigiCert

http://timestamp.digicert.com

支持 RFC 3161,可用于 Microsoft Authenticode 等代码签名场景。

Certum

http://time.certum.pl

支持:

  • Authenticode
  • RFC 3161

Certum 官方代码签名资料覆盖 Windows 和 Java JAR 签名场景。

GlobalSign

http://timestamp.globalsign.com/tsa/r45standard

当前 GlobalSign 代码签名资料使用该 RFC 3161 时间戳地址。

不建议继续使用已经不在当前官方代码签名文档中的历史 GlobalSign 地址。

SSL.com

http://ts.ssl.com

支持 RFC 3161,不支持传统 Authenticode 时间戳协议。

如果目标签名工具或旧系统对 TSA 使用的密钥算法存在兼容性限制,应在生产接入前进行实际验证。

时间戳服务器对比

提供商地址AuthenticodeRFC 3161
Microsofthttp://timestamp.acs.microsoft.com未确认支持
Sectigohttp://timestamp.sectigo.com支持支持
DigiCerthttp://timestamp.digicert.com未确认支持
Certumhttp://time.certum.pl支持支持
GlobalSignhttp://timestamp.globalsign.com/tsa/r45standard未确认支持
SSL.comhttp://ts.ssl.com不支持支持

表中的“支持”描述的是对应提供商公开资料所确认的协议能力。

时间戳服务策略可能发生变化,生产配置前应重新核对提供商当前官方资料。

受限时间戳服务

部分时间戳服务器虽然提供 RFC 3161 服务,但不能直接作为匿名公共 TSA 使用。

QuoVadis

公开的 RFC 3161 地址包括:

http://ts.quovadisglobal.com/eu
http://ts.quovadisglobal.com/ch

该服务要求预先注册调用方出口 IP,因此接入前需要完成相应授权。

Apple

http://timestamp.apple.com/ts01

属于 Apple 代码签名生态使用的时间戳服务。

不应将其直接作为 Windows Authenticode 的通用时间戳服务器。

测试型时间戳服务

某些公开 RFC 3161 服务更适合协议测试,而不是直接作为生产代码签名 TSA。

例如:

https://freetsa.org/tsr

这类服务可能使用自己的 CA 和 TSA 证书。

因此不能假定:

Windows
macOS
Java
其他代码签名验证器

默认都会信任其证书链。

生产环境应使用目标平台实际验证签名产物。

生产环境检查

将一个时间戳服务器加入生产配置前,建议至少确认:

  1. 服务商官方资料明确公布该端点。
  2. 服务商明确支持所需时间戳协议。
  3. 使用 SHA-256 或更强的时间戳摘要算法。
  4. 目标系统能够验证 TSA 的完整证书链。
  5. DNS、代理、防火墙和出口网络可以稳定访问 TSA。
  6. 已确认认证方式、速率限制、区域限制和服务条款。
  7. 使用实际签名产物完成验签测试。

不要仅通过:

浏览器可以打开
HTTP 返回 200

判断时间戳服务器是否适合代码签名。

必须使用实际签名工具发送时间戳请求,并对最终产物执行验证。

时间戳选择建议

对于现代 Windows SHA-2 代码签名,通常优先选择支持 RFC 3161 的时间戳服务。

例如:

Microsoft
Sectigo
DigiCert
Certum
GlobalSign

最终选择应综合考虑:

  • 目标操作系统。
  • 签名工具。
  • TSA 证书链。
  • 网络可达性。
  • 区域限制。
  • 调用频率限制。
  • 服务条款。
  • 服务等级协议。
  • 实际签名产物验证结果。

如果证书提供商对时间戳服务有明确要求,应优先遵循对应证书策略和服务商要求。

相关集成方式

不同集成方式会使用本页中的签名次数和时间戳规则:

使用场景文档
SignTool CLI客户端工具
Windows KSP / CSPWindows Provider
JarsignerJava 集成
GitHub Actions、Electron Builder、Advanced InstallerCI/CD 与构建工具
直接调用远程签名接口API 集成