证明:PyPI上的新一代签名
在过去的⼀年中,我们与Python包索引(PyPI)合作,为Python生态系统开发了⼀项新的安全功能:索引托管的数字证明,具体规范见PEP 740。
这些证明通过提供关键的可⽤性、索引可验证性、加密强度和来源属性,改进了传统的PGP签名(已在PyPI上禁⽤),使我们离实现软件供应链的全局加密可验证来源更近了⼀步。
好消息是:如果您已经使⽤可信发布(Trusted Publishing)向PyPI发布包,可能⽆需更改任何内容:官⽅PyPI发布⼯作流已内置证明⽀持,⾃v1.11.0及更新版本起默认启⽤。换句话说,只要您已经使⽤(或升级到)pypa/gh-action-pypi-publish@v1.11.0或更新版本,并配置了可信发布者,您的包将默认获得构建来源证明!
默认启⽤是我们的关键设计约束:我们希望⼀个证明功能能够与现有发布身份集成,规避传统数字签名设计中反复出现的密钥和身份管理挑战。Sigstore⾃然成为这些挑战的解决⽅案:其对基于身份的⽆密钥签名的⽀持,提供了PyPI对可信发布和包来源⽀持之间的公开可验证链接。
查看官⽅PyPI⽂档以获取有关如何创建和使⽤索引托管证明的实⽤信息,并在此处阅读我们的技术摘要,了解这些证明的⼯作原理以及我们对未来发展的看法!
也请阅读PyPI博客上的官⽅公告!
背景:可信发布
去年,我们与PyPI合作设计并实现了可信发布,这是⼀种更新、更⽅便、更安全的向PyPI上传包的⽅式。由于其可⽤性优势,我们在过去的18个⽉中看到可信发布取得了巨⼤成功:超过19,000个独⽴项⽬注册了可信发布者,这些项⽬共同使⽤可信发布向PyPI发布了近50万个⽂件:
我们有⼀篇关于可信发布和PyPI的完整博客⽂章,但简要总结如下:
- 可信发布消除了对⼿动配置和限定范围的API令牌的需求。
- 项⽬声明批准的可信发布者(GitHub、GitLab、Google Cloud Build、ActiveState等)身份,这些身份可以上传新版本。
- 为确保这些身份请求的真实性(即声称是它们的CI/CD⼯作流),可信发布通过OpenID Connect(OIDC)使⽤公钥加密。
- OIDC流程允许可信发布者⾃动获取PyPI API令牌,⽆需⽤户⼲预,减少了凭据泄漏和意外过度限定范围等⽤户错误的机会。
- 通过此OIDC流程颁发的令牌是短寿命且范围最⼩化的,减少了攻击者囤积它们以备将来使⽤或通过单⼀凭据在不同项⽬之间⽀点的能⼒。
PyPI上可信发布的成功也引起了其他生态系统的兴趣:RubyGems在⼏个⽉后实现了它,⽽Rust的crates.io有⼀个开放RFC!
从可信发布到Sigstore
可信发布将PyPI托管的项⽬与处理发布的加密可验证机器身份(例如github.com/example/example的release.yml)连接起来。
这对于消除⼿动API令牌流程⾮常有益,但它也为我们提供了更基本的东西:来源!
特别是在GitHub(或GitLab等)打包⼯作流的上下⽂中,OIDC凭据中的机器身份为我们提供了类似“发布来源”的东西:⼀组关于存储库和⼯作流状态的声明,对应于包发布到PyPI的时间。
然⽽,以OIDC凭据的形式,这种来源对外部⽤户来说并不⽴即有价值:
- PyPI不能共享凭据本⾝,因为它本质上是秘密材料。即使有适当的控制(过期和固定受众),个⼈信息泄露和⾏为不端的JWT验证器的⻛险也太⼤,⽆法冒险进⾏外部(⾮PyPI)验证。
- PyPI可以披露凭据中的声明,例如通过发布元数据,内容为“项⽬sampleproject由从pypa/sampleproject运⾏的GitHub⼯作流pypi-publish.yml发布”。这将导致⼀种模型,其中下游⽤户被迫信任PyPI诚实地提供这些声明。
这就是Sigstore的⽤武之地。我们有另⼀篇关于Sigstore及其⼯作原理的完整博客⽂章,但对我们⽬的的关键部分是,Sigstore通过⼀个免费、公开可访问、可审计的证书颁发机构(Fulcio)将短寿命签名密钥绑定到机器身份。
Fulcio接受OIDC凭据形式的机器身份,这意味着PyPI的可信发布流程隐式兼容Sigstore签名:可信发布者所需要做的就是向Fulcio提交带有OIDC凭据的证书签名请求,并接收⽤于后续使⽤的签名证书。
Fulcio将把OIDC凭据中的适当声明嵌⼊公共证书中,为我们提供⼀个公开可验证的来源,⽆需披露凭据本⾝或单⽅⾯信任PyPI正确提供它!
其中涉及的步骤可能有点难以理解,因此让我们可视化它们。以下是Sigstore参与之前的“传统”可信发布流程:
然后,在Sigstore加⼊后:
请注意,虽然流程中多了⼀个实体(Sigstore),但从⽤户的⻆度来看没有任何变化:他们所需要的只是他们的⼀次性可信发布者配置,这来⾃原始流程。
从Sigstore到证明和来源
Sigstore通过为我们提供⼀个公共可验证的凭据(以X.509证书的形式),将临时密钥对绑定到机器身份(例如发布到PyPI的GitHub存储库和⼯作流),从⽽缩⼩了可信发布和来源之间的差距。
然⽽,还有⼀步:Sigstore颁发的证书绑定到可信发布身份,但它本⾝并不为正在发布的东西(即实际的Python包分发)签名。
为了覆盖后者,我们需要使⽤我们的临时密钥对对包分发的证明进⾏签名,加密将分发⾃⾝的身份(其名称和摘要)与其来源(实际⽣成它的GitHub存储库或其他来源)绑定在⼀起。
这就是PEP 740的⽤武之地。PEP 740通过固定的证明有效负载将Sigstore和可信发布与实际包分发结合起来,本⾝在in-toto证明框架的范围内定义。
以下是⼀个实际证明的示例,为sigstore v3.5.1⽣成:
然后,这些证明由临时密钥对的私钥部分签名,本⾝绑定到X.509证书,以PyPI本⾝可验证的⽅式完成分发身份(⽂件名和摘要)与来源(嵌⼊X.509证书的OIDC声明)的完整绑定(因为OIDC声明对应于⽤户注册的可信发布者身份)。
当然,仅仅⽣成证明是不够的——这些证明还需要存储,以便⽤户可以⾃⾏验证它们!PEP 740也定义了这⼀点:上传带有证明的分发在JSON简单API中获得⼀个来源键,并在PEP 503索引中获得相应的数据来源属性。
这些字段包含指向“来源”对象的URL,该对象是每个分发的⼀个或多个证明对象的汇总,以及PyPI⽤于验证这些证明的可信发布者身份。我们可以深⼊研究这些内容,以回到我们上⾯的原始有效负载:
这让我们处于什么位置?
截⾄10⽉29⽇,证明对于任何通过PyPA发布操作使⽤可信发布的⼈来说都是默认的。这意味着⼤约20,000个包现在可以默认证明其来源,⽆需任何更改。我们预计这个数字还会随着时间的推移⽽增加,因为更多项⽬(尤其是新项⽬)默认使⽤可信发布,作为⼿动配置API令牌的⽤户友好且更安全的替代⽅案。
然⽽,产⽣证明的包总数只是⼀个视⻆,⽽且可以说是⼀个不完整的视⻆:包证明的价值与该包的“重要性”密切相关——即依赖它的⽤户或下游的数量。PyPI不知道项⽬的依赖关系,但总下载量是项⽬在生态系统中相对重要性的强有⼒代理。
为了深⼊了解后者,我们构建了“Are We PEP 740 Yet?”,它跟踪PyPI上360个下载量最⼤的包对PEP 740证明的采⽤情况:
截⾄⽬前,360个下载量最⼤的包中有5%已上传证明。但有⼀个混淆因素:约三分之⼆的下载量最⼤的包⾃证明启⽤以来根本没有更新,这意味着我们尚不知道⼀旦它们发布新版本,有多少会有证明!
我们从这⾥去哪⾥?
所有这些⼯作中明显缺少⼀件事:下游验证。
如所指定,PEP 740仅关⼼索引本⾝:它告诉PyPI如何接收和验证证明以满⾜其⾃⾝⽬的,以及如何在公共索引端点重新分发它们,但它没有强制要求(甚⾄没有定义)安装客户端(如pip和uv)的验证流程。
在实践中,这意味着索引托管证明的短期影响有限:它们为PyPI中使⽤的可信发布者身份引⼊了透明度,但下游客户端仍然需要信任PyPI本⾝诚实地提供证明。
这不是⼀个可接受的最终状态(加密证明只有在实际验证时才有防御属性),因此我们正在研究将验证带给单个安装客户端的⽅法。特别是,我们⽬前正在为pip开发⼀个插件架构,使⽤户能够将验证逻辑直接加载到他们的pip安装流程中。
⻓期来看,我们可以做得更好:进⾏“⼀次性”验证意味着客户端不记得哪些身份应该被信任哪些分发。为了解决这个问题,安装⼯具需要⼀种对签名身份的“⾸次使⽤信任”概念,意味着如果证明身份发⽣变化(或包在版本之间变得未证明),后续安装可以被⽤户停⽌和检查。
如果这听起来像⼀个锁⽂件问题,那是因为它就是!我们正在密切关注PEP 751,因为它定义了我们需要在其中存储预期分发身份的元数据格式。⼀旦Python生态系统开始采⽤标准化锁⽂件,我们将能够使⽤它们来存储和验证身份,就像今天使⽤哈希验证分发完整性⼀样。
总的来说,在常⻅默认安装流程在底层验证证明之前,我们还有⼀段路要⾛。但是,与早期索引托管签名的尝试不同,我们很清楚如何到达那⾥。然⽽,与此同时,有⼀些群体可以早期利⽤PyPI新托管的证明:
- 研究者:PEP 740证明构建在Sigstore之上,并提供了源存储库和包(如它们在PyPI上出现)之间缺失的关键可验证链接。这使它们成为安全和供应链研究的绝佳数据来源!
- 事件响应者:当可⽤时,证明⼤⼤缩短并简化了事件调查中最令⼈讨厌和容易出错的部分:跟踪特定⼯件回到其来源,准确找出它何时以及如何产⽣,等等。
- 完全控制其构建系统的⽤户:如果您维护⼀个完全控制其Python包依赖关系(即不使⽤pip或其他⼯具进⾏解析和安装)的开源或专业项⽬,那么您可能可以直接将证明验证纳⼊构建过程!查看我们的pypi_attestations⽂档作为起点。
如果您喜欢这篇⽂章,请分享: Twitter LinkedIn GitHub Mastodon Hacker News
⻚⾯内容
- 背景:可信发布
- 从可信发布到Sigstore
- 从Sigstore到证明和来源
- 这让我们处于什么位置?
- 我们从这⾥去哪⾥?
最近⽂章
- 构建安全消息传递很难:对Bitchat安全辩论的细致看法
- 使⽤Deptective调查您的依赖关系
- 系好安全带,Buttercup,AIxCC的评分回合正在进⾏中!
- 使您的智能合约成熟超越私钥⻛险
- Go解析器中意想不到的安全隐患
© 2025 Trail of Bits。 使⽤Hugo和Mainroad主题⽣成。