Kettle:用于可验证软件溯源的经认证构建

Lobsters Hottest 论文

摘要

本文介绍了 Kettle,一种经认证的构建系统,利用可信执行环境(TEE)生成加密可验证的软件溯源信息。它旨在通过将溯源文档直接与硬件签名的认证报告绑定,消除构建基础设施和操作人员对信任模型的影响。

<p><a href="https://lobste.rs/s/pu6cxi/kettle_attested_builds_for_verifiable">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/05/12 07:44

# Kettle:用于可验证软件来源的已认证构建

来源:https://arxiv.org/html/2605.08363(2026年4月)

###### 摘要

Kettle 是一个已认证构建系统,能够为可信执行环境(TEE)中构建的软件生成加密可验证的来源证明。Kettle 构建会在受测量的机密虚拟机内部生成一份来源文档,记录源代码提交、依赖集、工具链、构建环境以及输出工件的摘要。该文档的 SHA-256 摘要被提交到 TEE 平台的认证报告数据字段中,因此由硬件签名的认证报告本身就是对来源证明的签名,其签名身份链追溯至 TEE 制造商的信任根,而非构建基础设施操作员。由于机密虚拟机(CVM)镜像本身是可复现的,其启动测量值是公开且稳定的,这使得构建请求方可以在提交任何输入之前预先对 CVM 进行认证,并可选择通过终止于 CVM 内部的 TLS 通道交付源代码,从而使构建端到端地保持机密性,主机永远不会以明文形式看到源代码。验证简化为针对供应商信任根的一次签名检查以及少量摘要比较,无需重新执行构建。这一结果消除了构建基础设施、其操作员以及工件分发通道,从而缩小了验证者在判断二进制文件是否与其声明的输入相对应时必须接受的信任面。

## 1 引言

### 1.1 动机

软件消费者经常执行由独立软件提供商构建的工件。例如,开发人员从注册表安装预编译的二进制文件、企业部署供应商容器镜像,或客户运行其允许检查源代码的托管服务。软件工件是一个相当复杂的构建系统的最终结果。开发人员编写源代码,该代码从版本控制系统中获取。依赖关系从软件包注册表或缓存中解析。编译器、链接器和构建脚本在运行特定环境变量和文件系统状态的情况下转换这些输入。操作系统、内核以及容器或虚拟机镜像定义了构建发生的执行环境。这些层中的任何更改都会影响最终分发的字节,进而影响消费者与之交互的软件的行為。

这些层中的每一层都呈现出攻击面。随后,软件提供商必须对其产生的工件的完整性和行为提供某些声明。消费者随后使用这些声明来建立对他们与之交互的来自该提供商的软件信任。该消费者通常可用的证据是操作性的:CI 日志、发行说明、签名的校验和、工件注册表元数据或由构建管道发出的来源文档。这些记录可能有用,但仅凭它们只能证明某个系统做出了陈述。它们并不能证明陈述是真实的。受损的构建运行器可以在编译期间注入代码,同时保持源代码库清洁。特权操作员可以更改工具链、缓存的依赖项、环境变量或工件上传步骤。有权访问工件存储的攻击者可以在构建完成后替换二进制文件。在每种情况下,消费者都会看到一个合理的发布记录,但工件可能不再对应于所声明的源代码和依赖项。

根本的差距在于,大多数构建系统并没有以独立可证明的方式将提供商的声明与实际软件工件绑定在一起。发布可能指向源代码提交、发布锁定文件、指定工具链并分发工件摘要,但这些事实通常是通过流程而非加密证据连接起来的。

弥合这一差距很困难,因为构建系统庞大、有状态,并且在语言、包管理器、操作系统和部署格式之间变化很大。任何有用的绑定都必须能够跨越这种复杂性进行扩展,并且验证必须保持足够快速和低摩擦,以便普通软件消费使用。

### 1.2 问题陈述

问题在于,针对特定的软件工件,确定提供商关于其来源的声明是否值得信赖。目标是将构建来源从断言转化为消费者可以独立验证的加密证据。任何实际解决方案都必须满足以下约束:

1. 软件消费者,或代表消费者行事的工具,可以在不检查提供商内部系统的情况下评估证据。
2. 在威胁模型中,证据不能被注册表、镜像、缓存或部署系统伪造或静默篡改,而未被验证检测到。
3. 该方法能够扩展以处理大量工件和消费者。
4. 验证效率足够高,适用于普通软件消费,而不仅仅是手动审计。
5. 该方法能够容忍不同的语言、依赖管理器、工具链、操作系统和工件格式。

期望的结果是加密可验证的构建来源。对于每个工件,提供商都会生成一份记录,说明它是如何构建的(它来自的源代码、使用的依赖项和工具链、运行的环境),并使用硬件根加密证据将该记录绑定到工件。消费者直接检查证据。如果任何相关输入、构建过程、环境或工件本身与记录所述不同,则验证失败。

### 1.3 范围

本文描述了 Kettle 的威胁模型和架构,Kettle 是由 Confidential.ai 开发的一种构建工具,用于创建和验证已认证构建。它涵盖了使已认证构建值得信赖的技术,描述了从源代码输入到输出工件的证据链,并将 Kettle 呈现为该系统的开源实现。它并不试图证明源代码是安全的、依赖项没有后门,或者编译器在语义上是正确的。认证证明来源和构建过程的完整性,而不是软件意图。

## 2 背景

### 2.1 软件构建

在本文的上下文中,软件构建是任何将输入转换为输出的过程。构建可以包括预处理、编译、链接、复制、打包或任何类型的文件生成。在创建提供高置信度以表明所述输入映射到给定输出的构建时,构建的具体重要方面包括:

- **输入**:源代码库、依赖项、工具链、配置文件
- **过程**:运行的构建脚本、工具选项、环境变量
- **环境**:操作系统、内核及其参数、文件系统和其他设备
- **输出**:二进制文件、容器、tarball 或其他生成的工件

**图 1 说明**:构建是一种多输入转换。源代码身份是必要的但不完整,因为依赖项、工具链、构建脚本和执行状态也会影响最终字节。

### 2.2 SLSA 软件来源

正如 Linux 基金会所述,“SLSA 是一个由行业共识建立的规范和逐步改进供应链安全的规范”[10](https://arxiv.org/html/2605.08363#bib.bib10)。除其他事项外,SLSA 规范为**来源**提供了具体格式,其定义为可用于追踪工件通过复杂供应链中的所有活动部分回到其来源的可验证信息。它是关于软件工件的可验证信息,描述某物是**在哪里**、**何时**以及**如何**产生的[10](https://arxiv.org/html/2605.08363#bib.bib10)。通过使用 SLSA v1.2 构建来源格式,Kettle 能够提供行业标准且机器可读的信息,将工件回溯到用于创建该工件的源代码和工具。

### 2.3 可信执行环境(TEE)

可信执行环境(TEE)是一种硬件强制的隔离边界,提供四种安全属性:

- **机密性**。TEE 内的私有内存在内核级别进行加密。内存页使用 CPU 安全处理器管理的密钥进行加密,因此虚拟机监控程序、主机操作系统和具有 DMA 功能的设备无法通过软件访问解密私有 TEE 内存内容。
- **完整性**。一旦软件在 TEE 中初始化,外部软件对受保护的来宾状态的修改将被检测到。重放攻击、数据损坏和内存重映射会在平台的威胁模型内触发硬件级故障。
- **可验证性**。TEE 生成启动时加载软件的加密测量值(摘要)。该测量值涵盖固件、内核、初始文件系统状态和用户空间,并在来宾操作系统开始执行之前由 CPU 的安全处理器计算。
- **认证**。TEE 生成签名的认证报告,将启动测量值绑定到由来宾提供的报告数据。这些报告由链接到硬件制造商信任根的密钥签名,主机上的任何软件都无法伪造。

**图 2 说明**:CVM 内的测量启动。虚拟机监控程序、主机操作系统、BIOS、设备驱动程序和云运营商位于机密性边界之外。内部,安全处理器将每个加载层(固件、initrd、内核、用户空间、部署工作负载)的摘要扩展为单个累积测量值,随后携带在认证报告中。

**实现**。AMD[6](https://arxiv.org/html/2605.08363#bib.bib6)和 Intel[7](https://arxiv.org/html/2605.08363#bib.bib7)当前的商用 TEE 在虚拟机边界实现了所有这四种属性。由此产生的环境称为机密虚拟机(CVM),其中私有来宾内存使用虚拟机监控程序从未拥有的密钥进行加密。这四种属性相互增强。主机软件不能再直接读取私有 CVM 内存或静默重写受测量的来宾状态,从而防止主机进行软件级数据外泄和篡改。只要硬件制造商值得信赖并且固件漏洞可以在被发现时修补,信任面就会缩小到 CPU 供应商和平台依赖的加密原语,取代了边界信任侧的管理员、虚拟机监控程序和主机操作系统。

## 3 先前研究

### 3.1 可复现构建

可复现构建通过使构建本身具有确定性来解决软件来源问题。当相同的源代码、依赖项、工具链、构建指令和环境在不同的机器上产生逐位相同的输出时,构建是可复现的。目标是使声明输入与输出字节之间的关系表现为稳定的映射关系以进行验证。给定的输入集应始终产生相同的工件,匹配的工件摘要应标识产生它的输入集。在该条件下,消费者不需要信任原始构建机器或其操作员。消费者或某些独立的重新构建者可以重新构建工件并比较摘要。如果本地生成的摘要与分发的工件摘要匹配,则工件对应于发布的输入。

**图 3 说明**:可复现构建通过独立重建来验证来源。原始构建和重新构建必须从相同的声明输入汇聚到相同的输出摘要。

许多项目致力于在开源生态系统中使这一目标变得实际可行。其中之一是可复现构建项目[1](https://arxiv.org/html/2605.08363#bib.bib1),该项目支持该生态系统许多部分的复现性努力。Lamb 和 Zacchiroli[2](https://arxiv.org/html/2605.08363#bib.bib2)调查了 Debian 发行版中复现性的现状,并讨论了其在供应链完整性中的作用,包括抵抗构建时篡改、二进制文件的独立验证以及对构建基础设施信任度的降低。

局限性是实际上的,而不是概念上的。许多生产构建不是确定性的。编译器嵌入时间戳,并行构建以不同顺序产生输出,链接器记录完整文件路径,归档工具保留不一致的顺序,生成的文件可能取决于主机状态。实现逐位相同的输出需要控制整个依赖树中的这些因素。链中任何地方的单个非可复现组件都会破坏保证。对照 §1.2[2](https://arxiv.org/html/2605.08363#S1.SS2) 中的约束,这就是可复现构建遇到麻烦的地方。在任意一组语言、包管理器和工具链中实现逐位确定性是很困难的,这给约束 5(工具链覆盖范围)带来了压力。

### 3.2 Nix 和可复现构建环境

Nix[3](https://arxiv.org/html/2605.08363#bib.bib3) 是一个包管理器和构建系统,它将软件构建描述为输入纯函数,保存在称为派生(derivations)的文件中。Nix 并不要求每个构建输出都是逐位可复现的,而是使构建环境本身变得可复现。派生文件或 flake 锁定标识了用于构建输出的源代码、依赖项、工具链和构建配方,Nix 使用这些标识符在任何机器上以相同的方式构建相同的软件。这与依赖解析可能随机器或时间而异的包管理器相比是一个重大改进。

这种区别很重要。可复现的构建环境本身并不意味着可复现的构建输出。如果编译器、链接器、归档工具、生成的文件或构建脚本包含非确定性,相同的固定源代码和编译器仍可能产生不同的工件。当底层工具链是确定性的时,Nix 可以支持可复现构建,但可复现性属性来自于受控环境和确定性构建行为的组合,而不仅仅是环境固定。

Nix 还在构建边界留下信任问题。派生散列证明了与特定 Nix 评估的一致性,但它并不能证明评估器、构建器或本地工具链诚实执行。受损的构建主机仍可以在评估后更改构建过程或输出。因此,Nix 提供了强大的输入和环境控制,可以是来源策略的一部分,但它本身并未提供硬件根证据,证明特定工件是由特定构建执行产生的。

### 3.3 可认证构建

可认证构建是在可信执行环境中运行的构建,并输出关于构建期间观察到的环境、输入和输出的硬件签名证据。验证随后成为对该证据的检查(签名、环境测量和摘要比较),而不是重新执行构建本身。信任锚点从构建基础设施及其操作员转移到 TEE 硬件及其认证链。

两个先前系统具体实现了这一想法。

**TEE Compile**,由 Automata Network 开发[4](https://arxiv.org/html/2605.08363#bib.bib4),在 AWS Nitro Enclave 中运行项目的构建。Enclave 内部的工作进程通过主机获取依赖项,构建项目,并发出工件字节、输入/输出哈希报告以及覆盖 Enclave 镜像的 PCR0 的 Nitro 认证文档的元组。验证将输入和输出哈希与报告进行比较,并检查 Enclave 镜像是否在...

相似文章