验证发布版本

如何通过校验和、GitHub 证明、Sigstore 签名、npm provenance 和 PyPI 证明,确认 npm、PyPI 或 GitHub 上的 zn-gate 版本由 usezn/zn 的发布工作流构建。

查看 .md

由 Release 工作流发布的每个 zn-gate 版本,都只会从 usezn/zn 仓库中的一个标签(tag)构建一次。第一个这样的版本,是 1.5.0-beta.1 之后发布的第一个版本(1.5.0-beta.2 或 1.5.0,以先发布者为准)。相同的文件随后会发布到 npm、PyPI 和 GitHub Release,不使用长期有效的发布令牌:npm 和 PyPI 通过受信任发布(来自 GitHub Actions 的 OpenID Connect)接受这些文件。

每个版本包含:

文件 说明
zn-gate-<version>.tgz npm 包
zn_gate-<pyversion>.tar.gz Python 源码分发包
zn_gate-<pyversion>-py3-none-any.whl Python wheel
SHA256SUMS 上述三个文件的 SHA-256 校验和
<文件>.sigstore.json 每个文件(包括 SHA256SUMS)的 Sigstore bundle(签名、证书和透明日志证明)

每个文件还有一份 GitHub 制品证明(SLSA 构建来源证明),npm 会为该包显示 provenance 声明,PyPI 会为每个 Python 文件保存一份证明。

哪个工作流签署了你的版本

从 1.12.0 起,文件由一个独立的可复用工作流 build-release.yml 构建、证明并签名;release.yml 会调用它的构建和签名作业,但无法访问其内部。这使构建来源证明达到 SLSA Build Level 3,并且 build-release.yml 是下面第 2 步和第 3 步中的签署者。1.11.x 及更早的版本由 release.yml 自身构建和签名(SLSA Build Level 2:在 GitHub 托管的 runner 上构建)。npm provenance(第 4 步)和 PyPI 证明(第 5 步)是在文件发布时生成的,因此对所有版本,它们指向的都是该标签处的 release.yml。

版本 签署工作流
1.12.0 及更高版本 usezn/zn/.github/workflows/build-release.yml
1.5.0-beta.2 至 1.11.x usezn/zn/.github/workflows/release.yml

Python 版本号使用 npm 版本号的 PEP 440 写法:1.5.0 在两边都是 1.5.0,npm 上的 1.5.0-beta.2 在 PyPI 上是 1.5.0b2。

1.5.0-beta.1 及所有更早的版本都是手动发布的,没有签名、证明或 provenance。 下面的检查对它们会失败。这是预期的结果,并不表示文件被篡改。要检查这些版本,请将其与仓库中带标签的源代码进行比较。

npm dist-tag

版本 npm dist-tag
X.Y.Z(正式版,比当前 latest 更新) latest
X.Y.Z(旧版本线的补丁) release-X.Y
X.Y.Z-beta.N beta
X.Y.Z-rc.N next
X.Y.Z-alpha.N alpha

预发布版本绝不会移动 latest。npm install zn-gate 安装最新的正式版;如需选择预发布版本,请使用 npm install zn-gate@beta(或 @next、@alpha)。

在下面的示例中,请将 v1.12.0 / 1.12.0 替换为你要检查的版本;对于 1.11.x 及更早的版本,请将 build-release.yml 替换为 release.yml。

1. 校验和

从 GitHub Release 下载这些文件和 SHA256SUMS,然后运行:

sha256sum --ignore-missing -c SHA256SUMS      # Linux
shasum -a 256 --ignore-missing -c SHA256SUMS  # macOS

校验和只能证明文件与 SHA256SUMS 一致。要知道它是谁生成的,请检查 SHA256SUMS 的签名(第 3 步)或证明(第 2 步)。

2. GitHub 制品证明

使用 2.49 或更高版本的 GitHub CLI:

gh attestation verify zn-gate-1.12.0.tgz \
  --repo usezn/zn \
  --signer-workflow usezn/zn/.github/workflows/build-release.yml \
  --source-ref refs/tags/v1.12.0

对每个文件都运行一次。它会检查该文件是否由 usezn/zn 的发布工作流从该标签构建。

3. Sigstore 签名

签名身份是该标签处的签署工作流:

  • 身份:https://github.com/usezn/zn/.github/workflows/build-release.yml@refs/tags/v1.12.0(1.11.x 及更早:https://github.com/usezn/zn/.github/workflows/release.yml@refs/tags/v1.11.0)
  • 颁发者:https://token.actions.githubusercontent.com

使用 sigstore-python:

python -m pip install sigstore
python -m sigstore verify identity \
  --bundle SHA256SUMS.sigstore.json \
  --cert-identity https://github.com/usezn/zn/.github/workflows/build-release.yml@refs/tags/v1.12.0 \
  --cert-oidc-issuer https://token.actions.githubusercontent.com \
  SHA256SUMS

使用 cosign(2.4 或更高版本;cosign 3 不需要 --new-bundle-format):

cosign verify-blob SHA256SUMS \
  --bundle SHA256SUMS.sigstore.json \
  --new-bundle-format \
  --certificate-identity https://github.com/usezn/zn/.github/workflows/build-release.yml@refs/tags/v1.12.0 \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

SHA256SUMS 上的有效签名,加上通过的校验和检查(第 1 步),即可覆盖这三个文件。你也可以用同样的方法,根据每个文件自己的 bundle 逐个验证。

4. npm

npmjs.com 上的包页面会显示 provenance 部分,把该版本与提交和工作流运行关联起来。在已安装 zn-gate 的项目中运行:

npm audit signatures

它会检查已安装包的注册表签名和 provenance 证明。你也可以直接查看这些证明:

npm view zn-gate@1.5.0 dist.attestations

5. PyPI

pypi.org/project/zn-gate 上的每个文件都有 provenance 部分(在“Download files”下打开文件详情)。要使用 pypi-attestations 在命令行中检查:

python -m pip install pypi-attestations
pypi-attestations verify pypi \
  --repository https://github.com/usezn/zn \
  pypi:zn_gate-1.5.0-py3-none-any.whl

6. 发布标签

从 1.12.0 起,标签 vX.Y.Z 由 Tag release 工作流使用 gitsign(Sigstore 无密钥签名)创建并签名:签名指向该工作流,而不是某个人,并且如果该提交的标签没有这个签名,Release 工作流会拒绝发布。使用 gitsign 0.17 或更高版本,在仓库的克隆中运行:

git fetch origin tag v1.12.0
gitsign verify-tag v1.12.0 \
  --certificate-identity https://github.com/usezn/zn/.github/workflows/tag-release.yml@refs/heads/main \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

1.11.x 及更早的标签没有签名。

如果有任何不一致

请不要安装这些文件。请按照 SECURITY.md 中的说明私下报告。