宣布 sigstore-python 稳定版发布 - Trail of Bits 博客
William Woodruff
2023年1月13日
开源, 供应链, 生态系统安全, 工程实践, 密码学
同时请阅读 Sigstore 博客上的官方公告!
Trail of Bits 激动地宣布 sigstore-python 的首个稳定版本发布,这是我们近一年来开发的 Sigstore 客户端实现!这项工作由谷歌开源安全团队(GOSST)慷慨资助,我们还与他们合作开发了 pip-audit 及其相关的 GitHub Actions 工作流。
如果您还不熟悉 Sigstore,我们撰写了一篇解释文章,包括 Sigstore 是什么、如何在您自己的项目中使用它,以及像 sigstore-python 这样的工具如何融入整体代码签名生态系统。
如果您想开始使用,只需一个 pip 安装命令:
$ echo 'hello sigstore' > hello.txt
$ python -m pip install sigstore
$ sigstore sign hello.txt
$ sigstore verify identity hello.txt \--cert-identity 'foo@example.com' \
一个可用、参考质量的 Sigstore 客户端实现
我们对 sigstore-python 的目标有两个:
- 可用性:sigstore-python 应提供极其直观的 CLI 和 API,具有 100% 的文档覆盖率以及实际示例。
- 参考质量:sigstore-python 只是正在开发的众多 Sigstore 客户端之一,包括 Go、Ruby、Java、Rust 和 JavaScript 等生态系统。我们不是最老的实现,但我们的目标是在简洁正确地实现 Sigstore 安全模型的复杂性方面成为最权威的实现之一。
我们相信在这个版本中我们已经实现了这两个目标。本文的其余部分将展示我们是如何做到的!
可用性:sigstore-python 面向所有人
sigstore CLI
Sigstore 项目的座右铭之一是“为所有人提供软件签名”,我们希望 sigstore-python 忠实于这一理念。为此,我们设计了一个公共 Python API 和 sigstore CLI,将晦涩的密码学细节抽象 away,留下几乎所有开发人员都熟悉的两个原语:签名和验证。
开始使用,我们可以从 PyPI 安装 sigstore-python,其名称为 sigstore:
$ python -m pip install sigstore
$ sigstore --version
sigstore 1.0.0
然后,我们可以创建一个输入进行签名,并使用 sigstore sign
执行实际的签名操作:
$ echo "hello, i'm signing this!" > hello.txt
$ sigstore sign hello.txtWaiting for browser interaction...
Using ephemeral certificate:
--
MIICwDCCAkagAwIBAgIUOZ3vPindiCHATxvCRQk/TC5WAd0wCgYIKoZIzj0EAwMw
NzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRl
cm1lZGlhdGUwHhcNMjMwMTEwMTkzNDI5WhcNMjMwMTEwMTk0NDI5WjAAMHYwEAYH
KoZIzj0CAQYFK4EEACIDYgAETb8dcUgXs31y6tjgsVy8KwfMEzVvhUVs7jlzcwkN
MLICjVvblYtWfFReYMEN8rM8mfglyAwcW+qY/I3klMnMcf/bna/yazzP7Mnnh1g1
dzlOXh14C9iZMDPIV0KHH5u2o4IBSDCCAUQwDgYDVR0PAQH/BAQDAgeAMBMGA1Ud
JQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBQdX9zi1TPEHw2uAkqaCE2ecWMLTDAf
BgNVHSMEGDAWgBTf0+nPViQRlvmo2OkoVaLGLhhkPzAjBgNVHREBAf8EGTAXgRV3
aWxsaWFtQHlvc3Nhcmlhbi5uZXQwLAYKKwYBBAGDvzABAQQeaHR0cHM6Ly9naXRo
dWIuY29tL2xvZ2luL29hdXRoMIGJBgorBgEEAdZ5AgQCBHsEeQB3AHUA3T0wasbH
ETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGFnS1KGwAABAMARjBEAiAns85i
YPmlq9RWfJOUwCRN4y5Lwvk3/Y1cWB9wNW4XMwIgBRfib3YbotTgGpB16F/5uf7r
mO2Jc7e0yElimghFFmkwCgYIKoZIzj0EAwMDaAAwZQIxAOh0Ob8Mi2lENgRNjMRe
L8r8rBoVRSi8BzJHcKAe+eTwLsjvsdryJ0yKg5HVHc2erQIwNpdUXD71OPqs3QQ4
Ka+Q2Pjcs+GV5TvaecGzJuQGbm2J5ZW5raPJrXngEGUldt0U
--Transparency log entry created at index: 10892071
Signature written to hello.txt.sig
Certificate written to hello.txt.crt
Rekor bundle written to hello.txt.rekor
在桌面上,这将产生一个 OAuth2 流程,提示您进行身份验证,而在支持的 CI 提供商上,它将智能选择环境 OpenID Connect 身份!
这将产生三个输出:
hello.txt.sig
:hello.txt 本身的签名hello.txt.crt
:签名的证书,包含验证签名所需的公钥hello.txt.rekor
:一个可选的“离线 Rekor 包”,可在验证期间使用,而不是访问在线透明日志
验证看起来几乎与签名相同,因为 sigstore CLI 智能地根据输入的文件名定位签名、证书和可选的 Rekor 包。要实际执行验证,我们使用 sigstore verify identity
子命令:
$ # 查找 hello.txt.sig, hello.txt.crt, hello.txt.rekor
$ sigstore verify identity hello.txt \--cert-identity foo@example.com \OK: hello.txt
(这些额外标志是什么?没有它们,我们只是验证签名和证书,任何人都可以在 Sigstore 中获得任何公共输入的有效签名。为了确保我们实际上在验证有意义的内容,sigstore CLI 强制您断言签名预期绑定到哪个身份,然后在证书验证期间进行检查!)
然而,这还不是全部!Sigstore 不仅适用于电子邮件身份;它还支持 URI 身份,可以对应于特定的 GitHub Actions 工作流运行或其他机器身份。我们可以使用 sigstore verify github
子命令对这些签名进行更深入的验证,这允许我们检查 GitHub Actions 运行器环境所做的特定声明:
$ # 更改为任何版本!
$ v=0.10.0
$ repo=https://github.com/sigstore/sigstore-python
$ release="${repo}/release/download"
$ sha=66581529803929c3ccc45334632ccd90f06e0de4$ # 下载发行版 + 证书和签名
$ wget ${release}/v${v}/sigstore-${v}.tar.gz{,.crt,.sig}$ # 验证扩展声明
$ sigstore verify github sigstore-${v}.tar.gz \--cert-identity \"${repo}/.github/workflows/release.yml@refs/tags/v${v}" \--sha ${sha} \--trigger release
这远远超出了我们仅用裸 sigstore verify identity
命令所能证明的内容:我们现在断言签名是由针对提交 66581529803929c3ccc45334632ccd90f06e0de4 的发布触发的工作流运行创建的,这意味着即使攻击者以某种方式破坏了我们的存储库操作并为新输入签名,他们仍然无法欺骗我们接受此发布的错误签名!
全新的 sigstore Python API
除了上述 CLI 之外,我们还稳定了一个公共 Python API!您可以使用此 API 执行 sigstore CLI 能够做的所有事情,以及更高级的验证技术(例如复杂的“策略”逻辑链)。
使用与上述相同的签名示例,但改用 Python API:
import iofrom sigstore.sign import Signercontents = io.BytesIO(b"hello, i'm signing this!")# 注意:identity_token() 执行交互式 OAuth2 流程;
# 查看 `sigstore.oidc` 的其他成员以获取其他凭据机制。signer = Signer.production()
result = signer.sign(input_=contents, identity_token=token)
print(result)
以及相同的基于身份的验证:
import base64
from pathlib import Pathfrom sigstore.verify import Verifier, VerificationMaterials
from sigstore.verify.policy import Identityartifact = Path("hello.txt").open()
cert = Path("hello.txt.crt").read()
signature = Path("hello.txt.sig").read_bytes()
materials = VerificationMaterials(input_=artifact,cert_pem=cert,signature=base64.b64decode(signature),offline_rekor_entry=None,
)verifier = Verifier.production()result = verifier.verify(materials,Identity(identity="foo@example.com",),
)
print(result)
Identity
策略对应于 sigstore verify identity
子命令,并暗示了 Python API 表达声明之间更复杂关系的能力。例如,以下是我们如何编写上述 sigstore verify github
验证的方式:
from sigstore.verify import Verifier
from sigstore.verify.policy import (AllOf,GitHubWorkflowSHA,GitHubWorkflowTrigger,Identity
)materials = ...verifier = Verifier.production()result = verifier.verify(materials,AllOf([GitHubWorkflowSHA("66581529803929c3ccc45334632ccd90f06e0de4"),GitHubWorkflowTrigger("release"),])
)
…表示所有子策略之间的逻辑 AND。
下一步是什么?
我们承诺对 sigstore-python 的 API 和 CLI 进行语义版本控制:如果您在 Python 项目中依赖 sigstore~=1.0
,您可以安全地假设我们不会在没有主版本升级的情况下对两者进行破坏性更改。
考虑到这一点,稳定的 API 使我们能够在 Python 打包生态系统中实现 Sigstore 的许多近期目标:进一步集成到 PyPI 和客户端打包工具链中,以及稳定我们相关的 GitHub Action。
与我们合作!
Trail of Bits 致力于 Sigstore 生态系统的长期稳定和扩展。如果您想参与 Sigstore 或正在与您的公司合作将其集成到您自己的系统中,请与我们联系!
如果您喜欢这篇文章,请分享:
Twitter
LinkedIn
GitHub
Mastodon
Hacker News
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
公众号二维码