只要和足够多的安全团队聊聊代码签名的话题,就会发现一种熟悉的模式。谈话通常从证书开始,接着转向密钥,然后是硬件令牌、HSM、FIPS等级……通常也就到此为止了。
将关注点停留在这一处是可以理解的。证书是可见的实体,而密钥保护则是监管机构最常提及的部分。但如果仔细审视过去几年中那些备受瞩目的软件供应链事件,其真正出错的根源往往并非因为有人从硬盘上复制了私钥。更常见的情况是,本不该被签名的文件被签名了;或者由本不该拥有访问权限的人进行了签名;又或者虽然签名过程正确,但组织内无人能说明具体签名了什么。
业界已在很大程度上解决了“私钥锁定”问题。CA/Browser Forum 2023年的基准规范变更,将硬件支持的密钥存储设为所有代码签名证书(无论扩展验证(EV)还是组织验证(OV))的默认设置。这是一项意义重大的进展。但这其实已是过去式的问题,我们有必要坦诚面对这一点。
如今,代码签名真正失效的地方其实在更高一层——即围绕证书的流程。本文正是探讨这一流程。它面向安全负责人、DevOps 团队,以及在那些将签名视为比单纯勾选复选框更重要事项的组织中制定政策的人员。

从存储到访问
硬件令牌和HSM堵住了这一漏洞。无法导出的密钥也就无法被偷偷复制。这是一项结构性改进,如今已成为基本要求。
现在的问题不再是“密钥会被盗吗?”,而是“谁能使用它、他们用它签署什么内容,以及是否有人在监视?”
这是另一个问题。一个被严格管控的密钥库会告诉你谁拥有访问权限,但访问权限并不等同于可见性。一旦签名请求到达密钥管理系统,该系统本身通常只能看到一个哈希值——即待签名内容的简短指纹。它无法判断该哈希值代表的是你的正式版安装程序、一个副项目,还是本就不该提交的内容。
强大的存储并不能回答这个问题。关键在于流程。
可见性差距
大多数组织对其代码签名状况的了解,远不如他们自己想象的那样全面。他们大致知道自己购买了哪些证书,可能也知道谁持有令牌,但往往无法有把握地告诉你,过去90天里有哪些文件是以他们名义签名的。
正如斯特凡·韦尼格所言:
“许多组织仍在‘盲飞’,他们基本上不知道有哪些证书,也不知道这些证书被用于什么用途。”
这个诊断比听起来要准确得多。确实存在证书发现工具,它们对 Web 服务器很有用。但要爬取一整套构建代理、开发人员工作站和 CI/CD 管道,以查明哪些内容实际上已被签名,这却是一个困难得多的问题,而且大多数现成的工具其实并未真正尝试解决这个问题。
解决之道并非加强封锁,而是让签名过程可追溯。这意味着要记录签名操作,明确记录哪个证书在何时对哪个工件进行了签名,并能够(在几秒内,而不是几周内)回答“该证书曾在哪些地方被使用过?”这个问题。
如果你的团队需要一周时间才能回答这个问题,那么无论你的关键存储系统多么强大,都说明存在可见性缺口。
集中采购
在一些出人意料地成熟的组织中,会出现这样一种隐蔽的现象:某家区域办事处、小型业务部门或新收购团队的某位员工,使用公司信用卡从一家安全团队实际上并未使用的证书颁发机构(CA)购买了代码签名证书。该证书正在为以贵公司品牌发布的真实软件进行签名。安全团队从未见过该证书,也没有相关的政策框架来规范此事。没有人跟踪证书的到期情况。这种情况发生得足够频繁,值得专门设计措施加以防范。
解决这一问题的原则很简单,但实施起来却出人意料地困难:只设一个“前门”。每一次代码签名证书申请、每一次内部密钥交接、每一次签名操作,都必须通过一个由中央统一管理的流程。绝不允许以“这个团队很特别”为由破例。也不允许开发和运维团队在系统之外自行商定密钥交换方式。
安全团队应垄断这一职能。这并非指采取强硬手段,也不意味着拖慢开发者的进度或增加官僚主义。这意味着,在组织内获取、管理和使用代码签名材料只有一种经过批准的方式,而这种方式的设计初衷,正是为了让正确的事情变得简单。
这种立场值得坚持。代码签名是少数几种因去中心化而带来非对称风险的安全功能之一。证书遗漏所造成的代价,远大于将所有操作都通过受管流程处理所产生的成本。
签名应纳入 DevOps 体系,而非置于其外
数字签名仅能证明某人对一段代码承担了责任,但并不能证明该代码是安全的。这种区别的重要性远超人们的普遍认知。使签名具有意义的,是签名之前发生的一切:代码审查、自动化安全测试、构建溯源、SBOM生成以及发布审批。如果这些上游检查措施未落实,或者即使存在但与签名步骤脱节,那么一个经过正确签名的二进制文件就只是一个“带签名的隐患”。
签名是构建流程中的一个阶段,而不是流程结束时的手动仪式。构建系统会自动请求签名。审批流程是规范化的,而非即兴而为。开发人员在日常工作中不会去考虑签名问题,就像他们不会去考虑编译一样——它会自动发生,并且会正确地完成。
如果开发人员将签名视为一个独立的、最后环节的手动步骤,需要手动协调完成,那么架构就已经偏离了。这个问题是可以解决的,而且值得解决。
配置灵活性是一项隐形的韧性测试
以下是一个适用于任何代码签名配置的实用诊断问题:
如果明天出于某种原因,我们需要将一个项目从一个证书切换到另一个证书,是否只需进行一次配置更改就能完成?还是说这意味着要逐一检查每个开发团队的所有构建脚本,并手动重写命令行选项?
这个答案比表面看起来更具启发性。它能让你了解自己对当前行业中频繁出现的强制性变更做好了多少准备:证书吊销、密钥泄露、有效期缩短、算法弃用、供应商更换等。
采用集中配置方式构建签名环境的组织,只需几天就能适应这些变化。而未采用这种方式的组织,原本应该是一次例行更换,却可能因此耗费数月时间。
这种敏捷性平时并不重要,直到某天它突然变得至关重要。
有效性问题:是麻烦,还是推动力?
代码签名证书有效期缩短的趋势(目前为一年期,截至2026年3月,行业最长有效期为15个月)并未显著降低那些已建立完善签名管理机制的组织的风险。无论您是每三年还是每年轮换一次证书,一旦密钥被盗且尚未被吊销,它将在数天内(而非数月)被滥用——但这种做法的好处在于能提升加密灵活性。
证书寿命缩短真正造成影响的,在于运维负担。那些仍需手动轮换证书的团队,每个轮换周期都会深有体会;而早期就实现了生命周期自动化的团队,则几乎不受影响。
这才是真正的转机。有效期变更正推动着自动化进程。而在代码签名领域,自动化是安全团队能够进行的最具杠杆效应的投资之一。有效期的缩短,使证书生命周期自动化从“锦上添花”变成了“结构性要求”。与其在截止日期压力下被迫接受,不如尽早主动拥抱这一变化。
加密敏捷性:从意识提升到架构构建
如今,大家对后量子通信都已有所耳闻。但真正从组织架构上做好准备、能够付诸行动的企业却寥寥无几。
加密敏捷性本质上是后量子准备就绪的实践版本。它指的是一种特性:当底层算法必须变更时,你的签名基础设施无需随之改变。你可以替换基础算法,而无需重写围绕它的处理流程。
关于当前实际情况的一点说明:首批支持PQC的HSM已陆续面世,各硬件厂商正在实施NIST选定的算法。诸如 Windows 签名格式和代码签名工具等平台级支持正在跟进,但通常会滞后一步。实际上,您可能在平台能够验证这些签名之前就已生成量子安全的签名,这意味着加密灵活性在于为这一过渡的双方做好准备,而不是与其中一方竞速。
关于代码签名,有几点值得澄清:签名并不像批量加密那样存在“先收集,后解密”的风险。即使五年后签名遭到泄露,也不会导致历史数据被追溯性地暴露。但你的系统架构应能确保在签名算法被破解或废弃时,能在短时间内重新签名——因为总有一天会有人遇到这种情况,而你肯定不希望在明天急需重新签名时,才第一次去了解相关流程。
无人监管的边疆
有一点值得特别指出,因为大多数关于代码签名的介绍都会悄无声息地略过这一点。
CA/Browser Forum 的基本要求适用于在微软、苹果、谷歌和 Java 生态系统中运营的公共证书颁发机构。这涵盖了很大一部分,但并非全部。
Linux 发行版、固件签名、主板签名、物联网设备签名以及内部软件包签名,这些都不受 CA/B 论坛的监管。这些领域曾发生过严重的公开事件,但即便如此,这些领域的规则在很大程度上仍由各组织自行决定。
如果你在上述任何一个领域开展业务,这意味着:你的内部流程就是法规。如果你投入不足,不会有外部标准来约束你。好消息是,本文中的原则在这些环境中同样适用,就像在主流代码签名中一样。这种架构具有可移植性。而自律则必须靠自己来坚持。
从证书到项目
如果从这一切中只能带走一个思维模型,那就是将代码签名从“证书”的视角转变为“程序”的视角。强健的密钥存储是该程序的一部分。它并非全貌,而假装它就是全貌,恰恰是那些备受瞩目的事件不断暴露出的漏洞所在。
一份关于更健康节目应具备哪些特征的简短清单:
- 清点:了解以您名义存在的证书有哪些,以及这些证书被用于签署了哪些内容
- 集中化:为采购、密钥发放和签名操作提供统一入口
- 集成:将代码签名作为 DevOps 流程中的一个阶段,而非最后阶段的手动交接
- 监控:对签名操作进行可视化管理,而不仅仅是访问密钥
- 敏捷架构师:假设证书、算法和规则会发生变化,并针对这些变化进行设计
这些措施单独来看都没有什么革命性。难点在于将它们视为一个相互关联的整体,而不是五个独立的项目,并明确指定一个人对全局负责。只要让这些环节协同工作,代码签名就不再像是一场反复上演的应急演练,而是真正成为基础设施的一部分——这种基础架构能让你即使在相关规则不断演变的情况下,也能日复一日地充满信心地发布软件。
这就是真实的情况。证书只是其中的一部分。
保护最重要的东西是我们一切工作的核心。只有全面考量,这种保护才能真正实现。