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

CI/CD 与构建工具

sslTrus 远程代码签名服务可以集成到 CI/CD、应用构建和安装包制作流程中,在编译或打包完成后自动对发布产物执行代码签名。

当前支持的典型集成场景包括:

  • GitHub Actions
  • Electron Builder
  • Advanced Installer

根据构建工具的能力,可以直接使用 sslTrus GitHub Action、调用 SignTool CLI,或通过构建工具提供的自定义签名接口完成集成。

GitHub Actions

sslTrus 提供官方 GitHub Action:

ssltrus-official/code-sign-action

可以直接在 GitHub Actions Workflow 中对构建产物执行远程代码签名。

Action 会调用 sslTrus 远程代码签名服务完成签名,并直接更新指定文件,适用于 Linux、macOS 和 Windows Runner。

准备 GitHub Secrets

建议将远程代码签名凭证保存到 GitHub Actions Secrets:

SSLTRUS_ACCESS_KEY
SSLTRUS_ACCESS_SECRET
SSLTRUS_CERT_CODE

不要将 Access Secret 直接写入 Workflow 文件。

基础配置

- name: Sign files
uses: ssltrus-official/code-sign-action@v1
with:
access-key: ${{ secrets.SSLTRUS_ACCESS_KEY }}
access-secret: ${{ secrets.SSLTRUS_ACCESS_SECRET }}
cert-code: ${{ secrets.SSLTRUS_CERT_CODE }}
files: build/app.exe

签名成功后,build/app.exe 会被签名后的文件直接替换。

签名多个文件

files 支持使用多行配置多个文件:

- name: Sign files
uses: ssltrus-official/code-sign-action@v1
with:
access-key: ${{ secrets.SSLTRUS_ACCESS_KEY }}
access-secret: ${{ secrets.SSLTRUS_ACCESS_SECRET }}
cert-code: ${{ secrets.SSLTRUS_CERT_CODE }}
files: |
build/app.exe
build/library.dll
build/installer.msi

也可以使用逗号分隔文件路径。

重复的文件路径只会处理一次。

完整配置

- name: Sign files
uses: ssltrus-official/code-sign-action@v1
with:
access-key: ${{ secrets.SSLTRUS_ACCESS_KEY }}
access-secret: ${{ secrets.SSLTRUS_ACCESS_SECRET }}
cert-code: ${{ secrets.SSLTRUS_CERT_CODE }}
files: |
build/app.exe
build/library.dll
build/installer.msi
dry-run: false
timestamp-rfc3161: http://timestamp.acs.microsoft.com
description: Example Application
description-url: https://example.com

主要参数:

参数必填默认值说明
access-key-sslTrus Access Key
access-secret-sslTrus Access Secret
cert-code-代码签名证书编号
files-需要签名的文件路径
nicsrsfalse是否使用 NICSRS 服务
dry-runfalse使用本地测试证书执行测试签名
timestamp-rfc3161autoRFC 3161 时间戳服务器
description-写入 Authenticode 签名的程序描述
description-url-写入 Authenticode 签名的程序 URL

完整 Workflow 示例

下面是在 Windows Runner 中编译、签名并上传构建产物的示例:

name: Build and Sign

on:
workflow_dispatch:

permissions:
contents: read

jobs:
build:
runs-on: windows-latest

steps:
- name: Check out repository
uses: actions/checkout@v7

- name: Build
run: |
# 在这里执行实际构建命令

- name: Sign files
uses: ssltrus-official/code-sign-action@v1
with:
access-key: ${{ secrets.SSLTRUS_ACCESS_KEY }}
access-secret: ${{ secrets.SSLTRUS_ACCESS_SECRET }}
cert-code: ${{ secrets.SSLTRUS_CERT_CODE }}
files: |
build/app.exe
build/library.dll
timestamp-rfc3161: http://timestamp.acs.microsoft.com

- name: Upload signed files
uses: actions/upload-artifact@v7
with:
name: signed-files
path: |
build/app.exe
build/library.dll

建议将签名步骤放在:

编译 → 打包 → 代码签名 → 发布

流程中的发布步骤之前。

多平台 Runner

GitHub Action 可以在不同 Runner 中调用:

strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest

runs-on: ${{ matrix.os }}

因此,即使构建任务运行在 Linux 或 macOS,也可以使用相同 Action 完成受支持文件的远程签名。

Dry Run

如果需要验证 Workflow 和文件处理逻辑,可以启用:

dry-run: true

此模式使用本地测试证书,不调用远程代码签名服务。

例如:

- name: Test signing
uses: ssltrus-official/code-sign-action@v1
with:
access-key: dummy
access-secret: dummy
cert-code: dummy
files: build/app.exe
dry-run: true

dry-run 仍会修改目标文件,因此不要将其理解为完全不修改文件的预览模式。

Electron Builder

Electron Builder 可以通过自定义签名函数调用 sslTrus SignTool CLI,从而在 Electron 应用构建过程中自动完成 Windows 可执行文件和安装包签名。

典型流程:

Electron Builder

customSign

SignTool CLI

sslTrus 远程代码签名服务

云端 HSM

前提条件

开始前需要:

  • 已有可用的 sslTrus 远程代码签名服务。
  • 已获得 Access Key 和 Access Secret。
  • 已获得代码签名证书编号。
  • Electron 项目使用 electron-builder 构建。
  • 构建环境能够执行 sslTrus SignTool CLI,可从 sslTrus 客户端发布页 下载。

配置凭证

可以通过环境变量将凭证传递给构建脚本:

Linux 和 macOS:

export SIGNTOOL_ACCESS_KEY="YOUR_ACCESS_KEY"
export SIGNTOOL_ACCESS_SECRET="YOUR_ACCESS_SECRET"
export SIGNTOOL_CERT_CODE="YOUR_CERT_CODE"

Windows PowerShell:

$env:SIGNTOOL_ACCESS_KEY = "YOUR_ACCESS_KEY"
$env:SIGNTOOL_ACCESS_SECRET = "YOUR_ACCESS_SECRET"
$env:SIGNTOOL_CERT_CODE = "YOUR_CERT_CODE"

这些变量由 Electron 自定义签名脚本读取,再传递给 SignTool CLI。

配置 Electron Builder

在:

electron-builder.mjs

或者项目实际使用的 Electron Builder 配置文件中,为 Windows 设置自定义签名函数:

export default {
win: {
target: [
{
target: 'nsis',
arch: ['x64'],
},
],
sign: customSign,
signingHashAlgorithms: ['sha256'],
},
};

其中 win.sign 是 Electron Builder 官方提供的自定义签名入口,详细说明请参阅 Electron Builder Windows 代码签名文档

customSign

负责调用 sslTrus SignTool CLI。

自定义签名函数

示例:

import { execFileSync } from 'node:child_process';

async function customSign(configuration) {
const {
SIGNTOOL_ACCESS_KEY,
SIGNTOOL_ACCESS_SECRET,
SIGNTOOL_CERT_CODE,
} = process.env;

if (
!SIGNTOOL_ACCESS_KEY ||
!SIGNTOOL_ACCESS_SECRET ||
!SIGNTOOL_CERT_CODE
) {
throw new Error('Missing sslTrus signing credentials');
}

execFileSync(
'./signtool',
[
'sign',
'--access-key',
SIGNTOOL_ACCESS_KEY,
'--access-secret',
SIGNTOOL_ACCESS_SECRET,
'--cert-code',
SIGNTOOL_CERT_CODE,
'--file',
configuration.path,
'--override=true',
'--sha1=false',
'--sha2=true',
'--timestamp-rfc3161=http://timestamp.acs.microsoft.com',
],
{
stdio: 'inherit',
},
);
}

建议使用参数数组调用子进程,而不是拼接完整 Shell 命令,以减少路径转义和特殊字符处理问题。

Electron Builder 会按照 signingHashAlgorithms 中的每个哈希算法分别调用一次签名函数。上面的示例只启用 SHA-256,因此每个文件调用一次。

执行构建

配置完成后,正常执行 Electron Builder:

npx electron-builder build \
--config electron-builder.mjs \
--win \
--x64

Electron Builder 在需要对文件执行签名时,会自动调用 customSign

一次 Electron 构建可能签名多个文件,例如:

MyApp.exe
helper.dll
update.exe
uninstall.exe
MyApp Setup.exe

因此,不应简单理解为“一次 Electron 打包只产生一次签名”。

实际签名次数取决于构建过程中有多少文件执行了远程签名。

Advanced Installer

Advanced Installer 是基于 Windows Installer 技术的安装包制作工具。

可以通过 Advanced Installer 的自定义签名工具功能调用 sslTrus SignTool CLI,使 MSI、EXE、CAB 等构建产物在打包过程中自动完成远程代码签名。

前提条件

需要准备:

  • sslTrus SignTool CLI,可从 sslTrus 客户端发布页 下载。
  • Access Key。
  • Access Secret。
  • 证书编号。
  • 已配置完成的 Advanced Installer 项目。

配置自定义签名工具

打开 Advanced Installer 项目的:

Digital Signature

配置页面。

启用代码签名后,将签名工具选择为:

Custom

签名工具路径设置为 sslTrus SignTool CLI 可执行文件。

例如:

C:\Tools\sslTrus\signtool.exe

自定义参数需要调用:

sign

子命令,并向客户端传入:

  • Access Key
  • Access Secret
  • Cert Code
  • SHA-2 签名设置
  • 时间戳服务器
  • 文件路径

建议优先通过安全方式提供 Access Key 和 Access Secret,避免将长期有效的 Access Secret 明文保存到可公开获取的项目文件中。

SignTool 参数示例

对应的签名逻辑类似:

signtool.exe sign ^
--access-key="YOUR_ACCESS_KEY" ^
--access-secret="YOUR_ACCESS_SECRET" ^
--cert-code="YOUR_CERT_CODE" ^
--nest=true ^
--sha1=false ^
--sha2=true ^
--timestamp-rfc3161=http://timestamp.acs.microsoft.com ^
--desc="Example Application" ^
--override=true ^
--file "app.exe"

在 Advanced Installer 中,实际文件路径应由其自定义签名工具机制传入,不要固定为示例中的 app.exe

构建配置

如果使用 Advanced Installer 自动签名安装包内部文件,需要同时检查构建和压缩方式。

根据项目实际配置,某些 CAB 归档方式可能会影响自定义签名流程,应确认最终需要签名的文件能够在对应阶段被调用。

配置完成后,可以在 Advanced Installer 的数字签名页面检查:

Files configured for signing

从而确认哪些文件将在构建过程中执行签名。

签名次数

Advanced Installer 可能在一次安装包构建过程中对多个文件分别执行签名。

例如:

文件签名
app.exe1 次
helper.dll1 次
uninstall.exe1 次
installer.msi1 次
合计4 次

因此:

一次构建 ≠ 一次签名

应根据实际完成远程签名的文件或签名动作数量计算。

签名次数

CI/CD 与构建工具通常会自动处理多个产物,因此签名次数需要特别关注。

基本原则:

签名次数 = 实际成功完成的签名动作数量

例如:

app.exe        → 1 次
library.dll → 1 次
installer.msi → 1 次

如果三个文件都成功签名:

合计 = 3 次

Electron Builder 和 Advanced Installer 等构建工具还可能自动生成并签名:

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

因此,应根据构建日志和实际签名产物确认签名次数,而不是按照 Pipeline 或 Build 的执行次数估算。

更多规则请参阅 参考资料

时间戳

正式发布的软件通常建议添加可信时间戳。

GitHub Actions、Electron Builder 和 Advanced Installer 集成均可以使用 RFC 3161 时间戳,例如:

http://timestamp.acs.microsoft.com

时间戳不属于新的代码签名操作,不单独增加代码签名次数。

不同 TSA 的协议支持和使用限制请参阅 参考资料

凭证安全

自动化环境中应特别保护:

Access Key
Access Secret
Cert Code

其中 Access Secret 应作为 Secret 管理,不应:

  • 提交到 Git 仓库。
  • 明文写入公开 Workflow。
  • 输出到构建日志。
  • 写入公开 Docker 镜像。
  • 通过不安全的方式传递给第三方构建系统。

GitHub Actions 建议使用:

GitHub Actions Secrets

其他 CI/CD 系统则应使用其对应的 Secret、Credential 或 Variable 管理机制。

如何选择

场景推荐方式
GitHub Actions WorkflowGitHub Actions
Electron 应用构建Electron Builder
MSI / EXE 安装包制作Advanced Installer
普通 Shell / PowerShell 自动化SignTool CLI
Windows 软件原生支持 KSPWindows Provider
自行开发签名流程API 集成

如果构建系统能够直接调用命令行程序,可以使用 SignTool CLI;如果工具已经提供标准的 Windows KSP/CSP 接口,则优先使用对应的 Windows Provider 集成方式。