gitsign,一种keyless 的方式来对 git commit 进行签名验证
文章目录
为何要进行 commit/tag 签名
对于 commit/tag 签名,可能大家的直观感受就是 GitHub 上一个绿色的 Verified
标志:
至于为什么需要对 git commit/tag 进行签名的原因一言以蔽之就是:证明代码的提交来自真正的作者,防止提交的代码被篡改,保证提交代码的安全性。
如果不对 commit/tag 进行签名,可以通过 git 的 --author="Author Name <email@address.com>"
来对 commit 信息的作者信息进行篡改,然后提交,这就导致了代码提交者有可能并不是真实的作者本人,如果提交的代码中有恶意代码,会对既有代码造成危害。签名验证就是为了保证代码的提交着和作者是同一个人。
对 commit/tag 进行签名验证的方法比较多,主流的有 GPG、SSH、X.509 证书等这种需要自己维护本地 key 的方式,也有 sigstore 新推出的 gitsign 这一 keyless 的签名方式。
commit/tag 进行签名的几种方法
使用 GPG 进行 commit/tag 签名
使用 GPG 对 commit 进行签名,通常有以下几步:
- 检查本地是否有 GPG key
使用如下命令查看本地是否有存在的 GPG key:
|
|
如果本地有现成的 key 而且可用则可以直接用来在 GitHub 上进行配置并进行使用。如果没有现成的 key 或者现有的 key 已经过期,则可以根据下面的步骤生成新的 key。
- (optional)生成 GPG key
GPG key 的生成可以通过命令 gpg --full-generate-key
来进行,详细步骤可以查看过往博客Kubernetes secrets 加密的几种方式。
生成之后可以用第一步中的命令进行查看:
|
|
- 添加 GPG key 到源代码托管平台
以 GitHub 为例说明如何讲 GPG key 添加到相应的源代码托管平台(其他系统类似)。
添加之前先要 list 出 GPG public key,使用如下命令即可:
|
|
7FECE0B631E4C7A4
是上一步 list 出来的 GPG key ID。
在 Settings –> SSH and GPG keys 中选择 New GPG key
并将上述内容粘贴进去点击 Add GPG key
即可。
- 配置 Git config
通过配置 Git config 来告知 Git 使用 GPG 进行签名:
|
|
本文示例的 GPG key ID 为 7FECE0B631E4C7A4
。
- 签名 commit
在代码变更之后使用 -S
进行 commit 签名:
|
|
在代码被推送到 GitHub 上,可以看到绿色的 Verified
徽章:
使用同样的方法也可以对 tag 进行签名。
|
|
在 tags 界面查看即可。在后续的演示中 tag 的签名均是一样的,不再重复演示。
使用 SSH 进行 commit/tag 签名
使用 SSH 对 commit/tag 签名的过程和使用 GPG 是一样的,首先需要一对 SSH key,可使用本地已有的,也可以使用 ssh-keygen
命令重新创建一对。再将 SSH key 添加到 GitHub 账号上,方法与 GPG 的添加一致。唯一有区别的在于以下几点:
- 将 SSH key 添加到 ssh-agent
使用 ssh-add
命令将 SSH key 的 private key 添加到 ssh-agent,同时会添加 passphrase 到 keychain(如有 passpharse 的话):
|
|
- 配置 Git config
通过配置 Git config 来告知 Git 使用 SSH 进行签名:
|
|
YOUR-SSH-PUBLIC-KEY 为生成或者使用既有的 SSH public key。
- 签名 commit
在进行代码变更之后使用如下命令进行签名:
|
|
推送代码到 GitHub,可以看到有了绿色的 Verified
徽章,可以查看签名信息:
从详细的签名信息可以看到是通过 SSH 进行签名的(列出了 SSH Key Fingerprint)。
使用 X.509 进行 commit/tag 签名
Smimesign 就是一种可以用 x509 证书来对 commit/tag 进行签名的方法。使用 Smimesign 进行签名的步骤如下:
- 确保有 X.509 证书
可以用 smimesign --list-keys
查看本地是否有证书存在,如果没有则可以在公共 CA 进行购买。本文演示用了自签名的证书并导入了 Keychain Access,证书信息如下:
|
|
smimesign 的安装可以查看安装指南。
- 配置 Git config
通过配置 Git config 来告知 Git 使用 X.509 证书进行签名。如果是对所有仓库进行配置,则执行如下命令:
|
|
如果只是针对单个仓库,执行如下命令即可:
|
|
配置签名的 key
,也即上述 list 出来的 certificate ID:2dd0bea94c9e6a55c9f4b86e78b7b9f2a976c96d
。
|
|
- 签名 commit/tag
在进行代码变更之后使用如下命令进行签名:
|
|
推送代码到 GitHub,可以查看签名验证信息:
显示
Unverified
是因为使用了自签名的证书,无法被 GitHub 信任。
以上可以看出,不管是使用 GPG、SSH 还是 X.509 证书对于 commit/tag 进行签名,本质都是用存储在本地的 secret key 进行签名的。这需要用户必须小心保护好保存在本地的签名 key。而下面要介绍的 gitsign 却是一种不需要自身维护本地 key 的签名方法。
关于 gitsign
gitsign 是 sigstore 的一个开源项目,通过 keyless 的方式进行 Git 签名。gitsign 受启发于 smimesign 项目,但是最大的不同是使用 keyless 的方式。
gitsign 的安装
gitsign 的安装非常方便,可以使用 Homebrew 进行安装:
|
|
也可以通过 go
命令进行安装:
|
|
通过 --help
或者 -v
来查看安装是否成功:
|
|
目前最新版本就是
0.3.1
。
gitsign 的使用
gitsign 使用之前,需要先进行配置,如果是针对单个仓库,执行如下配置:
|
|
如果配置对所有仓库生效,执行如下配置:
|
|
接着使用 git commit
进行代码提交:
|
|
浏览器会弹出如下界面:
选择一种登录方式,本文选择使用 GitHub 账号进行登录,点击 Log in with GitHub
,随后会跳转到http://localhost:55378/auth/callback?code=prlznslbnfteh7w7xscqcpiq3&state=2Fd3Pr0UlZa828WOi2HnPibGzIn并出现 Sigstore Auth Successful 的界面:
签名结束会在命令行有如下输出:
|
|
接着推送到 GitHub 对应的仓库即可,在 commit 界面看到显示为**Unverified
**:
点击 Unverified 可以看到签名证书的信息:
之所以显示 Unverified
是因为:
- sigstore 的 CA root 并不是 GitHub trust root 的一部分
- 因为 Gitsign 的临时密钥只在短时间内有效,使用标准的 x509 验证会认为证书过期后无效。验证需要包括通过 Rekor 进行的验证,以验证证书在使用时是否有效。
sigstore 团队期望能和 GitHub 团队通过协作在将来解决这个问题,让验证变成绿色的 Verified
。
可以看到用 gitsign 进行签名的时候,不需要本地先生成用户签名的 key,在执行 commit 的时候会从 fulcio 获取用于签名的证书,然后用这些证书信息对 commit 进行签名,并将签名信息上传到 rekor。整个过程像 keyless 一样。更多关于 flucio、rekor 的内容,可以查阅sigstore 官网。
文章作者 马景贺(小马哥)
上次更新 2022-10-11