代码签名与公证
本教程共 45 篇 · 第 34 篇 · 更新于 2026-08-03
34. 代码签名与公证
你精心打包好的安装包,用户双击却弹出「无法验证开发者」「应用已损坏」。这不是 bug,而是操作系统在保护用户:未签名的应用会被拦在门外。代码签名就是给应用贴上「这是我开发的」的电子身份证。本章讲清 Windows 与 macOS 两套签名体系,以及它们的安全意义。
本节目标
- 理解代码签名解决了什么问题。
- 掌握 macOS 的「签名 + 公证」两步流程。
- 了解 Windows 的 EV 证书与 Azure 云签名两种路径。
- 知道如何在 Forge 里配置签名参数。
- 明白签名与用户信任之间的关联。
1-1 为什么一定要签名
代码签名是一项安全技术,用来向操作系统和用户证明:这个应用确实由你发布,且发布后未被篡改。Windows 和 macOS 都会拦截未签名应用的运行。你可以不签名就分发,但用户必须手动绕过重重安全警告才能打开,体验极差且极易被误判为恶意软件。
更重要的一点是信任累积。Windows 的 SmartScreen 筛选器会根据签名记录给应用建立信誉。长期用同一张证书签名的软件,警告会越来越少;而完全未签名的软件,每次都会被拦。
提示:签名不等于「官方审核通过」。它只证明身份与完整性,不保证应用无害。是否安全最终仍由用户与系统判断。
1-2 macOS:签名与公证
在 macOS 上发布应用需要两步。先代码签名,再公证(notarization)。公证是苹果把你的应用上传到服务器,由自动化系统进一步扫描,确认它没有危害用户的行为。
开始之前要满足三个条件:加入 Apple Developer Program(每年付费)、安装 Xcode、在开发者后台生成并安装签名证书。Electron 生态崇尚配置自由,因此签名方式有多种,但本章以 Forge 为主线。
在 Forge 的 packagerConfig 里加入 osxSign 与 osxNotarize:
// forge.config.js
module.exports = {
packagerConfig: {
osxSign: {},
osxNotarize: {
appleId: 'you@example.com',
appleIdPassword: 'abcd-efgh-ijkl-mnop', // 应用专用密码
teamId: 'ABCDEFGHIJ',
},
},
};
appleIdPassword 不是你的 Apple 账号密码,而是在苹果账号里生成的「应用专用密码」。teamId 在开发者后台可查。配置好后,npm run make 会在打包时自动完成签名与公证上传。
公证是异步过程,上传后苹果会扫描几分钟到几十分钟。通过后,应用带上了「ticket」,用户首次打开时 Gatekeeper 才会放行。若失败,终端会给出具体原因,常见于缺少「 hardened runtime」或调用了被禁用的 API。
若你想上架 Mac App Store,流程另有一套(需 mac-app-store 专用证书),详见官方 Mac App Store 提交指南,本章不展开。
1-3 Windows:代码签名
Windows 的签名体系与 macOS 不同,微软允许开发者在市场上自由购买签名证书。自 2023 年 6 月起,微软要求用「扩展验证」证书,也就是 EV 代码签名证书。旧的普通(OV)证书已不再提供信誉加成,系统会把它当作未签名处理。
路径一:Azure Artifact Signing(推荐)
Azure Artifact Signing(原名 Azure Trusted Signing)是微软官方的云签名服务,价格最低,且能消除 SmartScreen 警告。它最大的优势是无需把证书下载到本地,特别适合 GitHub Actions 等 CI 环境。
在 Forge 里配置 Windows 签名,关键是 windowsSign:
// forge.config.js
module.exports = {
packagerConfig: {
windowsSign: {
// 使用 Azure Key Vault 进行云签名(Azure 云签名的常见形式,证书无需下载到本地)
signWithParams:
'--azure-key-vault-url=https://your-vault.vault.azure.net ' +
'--azure-key-vault-tenant-id=YOUR_TENANT ' +
'--azure-key-vault-client-id=YOUR_CLIENT ' +
'--azure-key-vault-client-secret=YOUR_SECRET ' +
'--azure-key-vault-certificate=YOUR_CERT',
},
},
};
Linux 或 macOS 上开发时,可用 jsign 工具通过 Azure 给 Windows 应用签名,无需 Windows 机器。
路径二:传统 EV 证书
你也可以购买传统 EV 证书(如 DigiCert、GlobalSign、Sectigo、SSL.com 等)。这类证书按规定必须存放在符合 FIPS 140 Level 2 的硬件模块中,外形像一枚高级 U 盘。很多供应商提供「云签名」方案,把硬件放在数据中心,你远程调用即可,这对 CI 友好。
无论哪种,所有 Electron 工具链都用 @electron/windows-sign 完成签名,配置都通过 windowsSign 传入。Forge 会用同一份配置签署应用本体和 Squirrel.Windows、WiX MSI 安装器。
1-4 在 Forge 中一处配置
注意一个设计细节:macOS 的签名走 osxSign / osxNotarize,Windows 的签名走 windowsSign,但它们都写在 packagerConfig 同一处。Forge 会根据当前打包的平台自动选用对应配置。这意味着你的 forge.config.js 可以同时写好两套,make 时只激活当前系统的那一套。
1-5 安全意义与分发前提
签名的核心价值是建立信任链。用户在安装前能看到开发者身份,系统能校验文件未被替换。没有签名,你的应用不仅被系统阻拦,还容易被第三方注入恶意代码而不被发现。
从分发角度看,签名是上架各大渠道的前置条件。Mac App Store、Windows Store、多数 Linux 软件源都要求签名(或特定格式)。即便你只放在官网提供下载,签名也能显著降低用户的顾虑。
提示:私钥与证书密码是最高机密,切勿提交到代码仓库。优先用 CI 环境变量注入,本地仅放占位配置。
常见误区
- 以为签名等于官方审核通过。签名只证明身份与完整性,不代表应用无害。
- 把证书密码写进仓库。私钥与密码应走 CI 环境变量,本地仅留占位。
- 用旧 OV 证书签 Windows。自 2023 年 6 月起微软只认 EV 证书,否则等同未签名。
- 只在本地测试 macOS 公证。公证是异步云端扫描,需在真实网络环境验证结果。
签名失败的常见信号
macOS 公证失败常因启用了被禁用的 API 或缺少 hardened runtime,终端会给出具体条目。Windows 若报「证书不受信任」,多为误用 OV 而非 EV 证书,或时间戳服务不可达。遇到这类问题,先读完整报错,再对照 Apple 或微软文档逐项修正,不要盲目重签。
小结
本章你了解了代码签名的意义,以及 macOS「签名 + 公证」与 Windows「EV 证书 / Azure 云签名」两条路径。签名在 Forge 里集中配置于 packagerConfig。下一章我们讨论生成安装包后,如何分发到用户手中并支持自动更新。