
在经历了 SolarWinds 供应链污染、XZ-utils 核心维护者后门注入等一系列触目惊心的全球网络安全事件后开源软件的交付信任体系正在经历一场深刻的信任重构。很多开源作者写好了一个 CLI 工具在 GitHub Actions 里交叉编译出针对 Linux、macOS 和 Windows 的二进制包打包成tar.gz挂在 Release 页面供用户下载。在这个看似自然的流转环节中隐藏着一个巨大的软件供应链信任黑洞终端用户凭什么相信从 GitHub Release 下载下来的二进制文件就是由公开的源代码在纯净环境中构建出来的如果维护者的 GitHub 账号被黑、个人访问令牌PAT泄露攻击者完全可以神不知鬼不觉地把 Release 附件里的二进制替换为一个捆绑了恶意挖矿或远控木马的恶意程序而源码树上的代码依然显示得干干净净。要彻底阻断这种篡改风险必须为构建产物注入可公开密码学溯源的数字签名Digital Signature。借助 Linux 基金会旗下 Sigstore 项目推出的Cosign工具与 GitHub Actions 的OIDCOpenID Connect无密钥签名机制Keyless Signing我们无需维护任何繁琐的传统 GPG 私钥就能在 CI 流水线中实现真正透明、防篡改的软件供应链安全防线。为什么传统的 GPG 签名走向没落在过去开源分发的标准做法是维护者用自己的 GPG 私钥对二进制进行本地签名生成.asc文件。但在实际工程落地中GPG 存在三个无法解决的硬伤私钥保管风险巨大很多开发者把自己的 GPG 私钥导成明文 Base64 塞进 CI 的 Secrets 环境变量里。一旦第三方依赖或 CI 容器存在漏洞私钥泄漏就意味着整个身份体系彻底崩溃。信任锚点模糊Web of Trust用户下载了二进制和.asc但由于没有全球权威的集中验证体系用户根本不知道去哪里核实这个 GPG 公钥是不是维护者本人的导致 99% 的普通用户直接跳过核验步骤。缺少防抵赖的时间戳透明存证攻击者拿到私钥后可以任意伪造两年前的旧版本签名难以证明签名行为发生的具体环境与上下文。Cosign 无密钥签名的破局机理Cosign 提出的“无密钥签名Keyless Signing”并不是真的不需要密钥而是消灭了需要人类长期保管的静态私钥OIDC 短期身份认领在 GitHub Actions 运行过程中Runner 通过id-token: write权限向 GitHub 的 OIDC 提供商申请一个有效期仅有数分钟的短期身份 JWT 令牌。该令牌中强绑定了当前代码仓库、Git 提交哈希、分支名称以及工作流文件路径。临时公私钥对生成与签署Cosign 在内存中生成临时的公私钥对利用私钥对二进制构建产物或校验和文件checksums.txt进行签名。短期证书签发Fulcio CACosign 将公钥与 OIDC 令牌提交给 Sigstore 的权威证书颁发机构 Fulcio。Fulcio 验证无误后签发一张绑定了该 GitHub 身份的极短效 X.509 数字证书有效期通常只有 10 分钟。公开透明日志存证Rekor Transparency Log签名记录、证书与元数据被永久写入公开的、只允许追加且防篡改的默克尔树账本 Rekor 中。私钥立焚签名完成的瞬间内存中的临时私钥被彻底销毁物理层面杜绝了私钥泄露的可能性。落地配置GitHub Actions 自动化签名流水线我们以一个典型的 Go 多架构二进制发布流水线为例展示如何在构建完成后自动完成 Cosign 签名并将证据链回传到 Release。在.github/workflows/release-signed.yml中编写name: Secure Build Sign Release on: push: tags: - v* # 核心权限声明必须开启 id-token: write 以便获取 GitHub OIDC 身份令牌 permissions: contents: write id-token: write jobs: build-and-sign: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkoutv4 with: fetch-depth: 0 - name: Setup Go 1.27.1 uses: actions/setup-gov5 with: go-version: 1.27.1 # 1. 安装 Cosign CLI 工具锁定官方 Action 签名 - name: Install Cosign uses: sigstore/cosign-installerv3.5.0 # 2. 执行跨平台构建并生成 SHA256 校验和清单 - name: Build Binaries run: | mkdir -p dist GOOSdarwin GOARCHarm64 go build -trimpath -o dist/mycli-darwin-arm64 GOOSlinux GOARCHamd64 go build -trimpath -o dist/mycli-linux-amd64 GOOSwindows GOARCHamd64 go build -trimpath -o dist/mycli-windows-amd64.exe cd dist sha256sum * checksums.txt cat checksums.txt # 3. 核心步骤使用 Cosign 对校验和清单进行无密钥签名 - name: Sign Artifacts with Cosign run: | # 针对包含所有二进制哈希的 checksums.txt 进行签名 cosign sign-blob \ --yes \ --bundle dist/checksums.txt.bundle \ dist/checksums.txt # 4. 发布带密码学签名的 GitHub Release - name: Upload Release Assets uses: softprops/action-gh-releasev2 with: files: | dist/* env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}终端用户的极速安全核验当用户从 GitHub Release 下载了客户端二进制后如何用单行命令验证其绝对纯正用户只需要安装cosign并在终端运行一条校验命令cosign verify-blob \ --bundle checksums.txt.bundle \ --certificate-identity https://github.com/my-org/my-project/.github/workflows/release-signed.ymlrefs/tags/v1.0.0 \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ checksums.txt如果校验通过Cosign 会在终端输出一条绿色的确凿信息Verified OK The following checks were performed each of them must pass: - The identity was verified: https://github.com/my-org/my-project/... - The certificate was verified against the Fulcio roots. - The transaction was verified against the Rekor log.随后用户只需要本地比对刚下载二进制的哈希sha256sum -c checksums.txt --ignore-missing这一整套链条在密码学层面提供了坚不可摧的证明防恶意篡改任何人试图把恶意木马伪装成同名二进制挂在 Release 上其计算出的哈希必然与被签名的checksums.txt不符防身份冒领checksums.txt的签名证书是由 GitHub OIDC 权威证明的确凿源自my-org/my-project的指定工作流其他黑客即使拥有自己的 GitHub 账号也无法伪造出目标仓库的身份证书可审计存证全世界任何人都可以通过公开的 Rekor 账本检索到某年某月某分某秒该发布行为的全部透明元数据。将数字签名沉淀为交付的标准动作是开源项目从“作坊式代码分发”迈向“企业级可信供应链”最重要的成年礼。