likes
comments
collection
share

维护代码的尊严:GPG签名让你的Git commit不再裸奔

作者站长头像
站长
· 阅读数 21

引言

GPG(GNU Privacy Guard)是一个强大的开源加密软件,它采用公钥加密和数字签名技术来保护数据的机密性和完整性。通过在Git提交中添加GPG签名,开发者可以确保提交的真实性,验证提交的作者身份,并提高代码的可信度。

作为一种公钥加密系统,GPG使用非对称密钥加密算法。每个用户拥有一对密钥:公钥和私钥。公钥用于加密数据和验证签名,而私钥用于解密数据和生成签名。

什么是签名?

签名是指使用私钥对数据进行加密,以证明数据的真实性和完整性的过程。在加密中,签名用于验证数据的来源和防止数据被篡改。

签名的过程如下:

  1. 数据生成:首先,使用哈希函数对要签名的数据进行处理,生成一个固定长度的哈希值。哈希函数是一种将任意长度的数据转换为固定长度输出的算法。
  2. 私钥加密:使用发送者的私钥对哈希值进行加密。这个加密操作产生一个数字签名,只有拥有相应私钥的发送者才能生成这个签名。
  3. 签名附加:数字签名与原始数据一起附加在一起,形成签名文件或签名数据包。
  4. 验证签名:接收者使用发送者的公钥来解密签名,从而得到原始的哈希值。
  5. 哈希比对:接收者使用相同的哈希函数对原始数据进行处理,生成一个哈希值。
  6. 比对校验:接收者将接收到的哈希值与使用公钥解密得到的哈希值进行比对。如果两个哈希值匹配,则验证成功,表明数据未被篡改并且确实来自于拥有对应私钥的发送者。

通过数字签名,接收者可以验证数据的完整性和真实性,确保数据在传输过程中没有被篡改或冒充。数字签名在保护数据的完整性、防止篡改和验证身份方面发挥着重要作用。

为什么要给Commit 签名?

Commit签名的主要目的是确保提交的代码在传输和存储过程中没有被篡改,并验证提交者的身份。通过为每个Commit添加数字签名,可以验证提交者的身份并确保代码的可追溯性。

是用GPG通过给Commit提交签名验证,可以在本地对标记和提交进行签名。 这些标记或提交在 GitHub 上标示为已验证,便于其他人信任更改来自可信的来源。如果提交或标记具有可加密验证的 GPGSSH、 或 S/MIME 签名,GitHub 会将提交或标记标示为“已验证”或“部分验证”。 维护代码的尊严:GPG签名让你的Git commit不再裸奔

签名流程

非对称加密

GPG使用非对称密钥加密算法,非对称加密是一种加密技术,使用不同的密钥对(公钥和私钥)来进行加密和解密操作。它也被称为公钥加密。

在非对称加密中,公钥是公开的,可以与他人分享,而私钥则保密保存在加密者的控制下。公钥用于加密数据,而私钥用于解密数据。因为公钥和私钥是一对密钥,它们彼此之间是相关的,但是无法通过公钥推导出私钥。

加密: 发送方使用接收方的公钥对要传输的数据进行加密。只有拥有与公钥对应的私钥的接收方才能解密该数据。

解密: 接收方使用自己的私钥对加密的数据进行解密,以获得原始数据。私钥是私有的,只有接收方能够访问它。

步骤

基于非对称加密,使用公钥加密和数字签名技术对Commit进行签名,签名Commit的过程涉及使用GPG的密钥对进行数字签名和验证。

  1. 生成密钥对:首先,使用GPG生成密钥对,包括公钥和私钥。私钥将被用于对Commit进行签名,而公钥将被用于验证签名。
  2. 配置Git:将生成的GPG公钥添加到Git的配置中,使其能够与GPG集成并使用对应的私钥进行签名。
  3. 签名Commit:在进行Commit操作时,使用Git命令行或相关的Git客户端,可以使用GPG的私钥对Commit进行签名。这将生成一个数字签名,将其与Commit一起提交到代码库。
  4. 验证签名:其他人在获取Commit时,可以使用对应的GPG公钥来验证签名的真实性。通过验证签名,可以确定Commit是由私钥的持有者生成的,确保数据的完整性和来源可信。

在签名Commit时,GPG使用了非对称密钥加密算法。私钥用于对Commit进行数字签名,而公钥用于验证签名。这种非对称加密的方法确保了签名的安全性和可靠性。 维护代码的尊严:GPG签名让你的Git commit不再裸奔

安装GPG

# 安装
brew install gnupg

# 解压
brew cleanup gnupg

生成 GPG 密钥

生成一个新的密钥,命令如下:

gpg --full-generate-key

它会弹出一系列问题让你输入,如实写入就好啦。

维护代码的尊严:GPG签名让你的Git commit不再裸奔

这是我选择的配置 具体情况看个人情况 然后输入密码就行 这个邮箱最好和Git邮箱一样

github 支持的密钥算法

  • RSA
  • ElGamal
  • DSA
  • ECDH
  • ECDSA
  • EdDSA

查看私钥信息

➜ gpg --list-secret-keys --keyid-format LONG
gpg: 正在检查信任度数据库
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深度:0  有效性:  1  已签名:  0  信任度:0-,0q,0n,0m,0f,1u
gpg: 下次信任度数据库检查将于 2024-04-07 进行
/Users/xxx/.gnupg/pubring.kbx 
--------------------------------
sec   rsa4096/D5BB89D6E7B84C0B 2023-04-08 [SC] [有效至:2024-04-07] # 公钥特征 rsa算法生成的 4096位 / 公钥id 生成时间
      716E599E76566F7C329BF7E7D5BB89D6E7B84C0B
uid                   [ 绝对 ] wakaka378 <gebilaofl@163.com>
ssb   rsa4096/EEC764C6A850B8F3 2023-04-08 [E] [有效至:2024-04-07]

主要信息如下

  • sec:表示这是一个私钥。
  • rsa4096:表示使用RSA算法,密钥长度为 4096 位。
  • D5BB89D6E7B84C0B:表示密钥的 ID,也就是公钥 ID 的后 8 位。
  • 2023-04-08:表示密钥的创建日期。
  • [SC]:表示这个密钥既可以用来签名(S),也可以用来加密通信(C)
  • 716E599E76566F7C329BF7E7D5BB89D6E7B84C0B:是密钥的完整 ID,与前面的 ID 相同,只不过多了前缀。
  • uid:表示这是一个用户 ID。后面包含该密钥的用户名 邮箱
  • ssb:表示这是一个子密钥,用于加密通信。
  • EEC764C6A850B8F3:表示子密钥的 ID,与主密钥 ID 相同。
  • 2023-04-08:表示子密钥的创建日期。
  • [E]:表示这个子密钥只能用于加密通信。

github部署公钥

到这一步, 如果我们直接将提交推送到GitHub上,提交上将会出现一个Unverified的标签, 这是因为, 虽然我们给提交签名了, 但是, GitHub还是不知道这个签名到底来自于谁。接下来,我们就要告诉GitHub: 我们这个用户所对于的公钥是哪个。

查看公钥id

gpg --list-keys

导出我们的公钥 将最后面的换成自己的公钥

gpg --armor --export 716E599E76566F7C329BF7E7D5BB89D6E7B84C0B

复制以-----BEGIN PGP PUBLIC KEY BLOCK-----开头并以 -----END PGP PUBLIC KEY BLOCK----- 结尾的 GPG 密钥。然后打开github --->settings ---> SSH and GPG kleysGPG keys栏中添加一个新的GPG key 将内容复制进去,然后输入密码。

维护代码的尊严:GPG签名让你的Git commit不再裸奔

配置git

git中启用签名功能,如果不配置 需要每次Commit后面加-S

git config --global commit.gpgsign true

gpg --list-secret-keys --keyid-format=long 查看一下私钥ID,执行下面命令,将D5BB89D6E7B84C0B换成自己的

git config --global user.signingkey D5BB89D6E7B84C0B

我这里是全局生效 如果只想在某个项目里 就去掉--global

GPG 密钥添加到 .zshrc 文件

if [ -r ~/.zshrc ]; then echo 'export GPG_TTY=$(tty)' >> ~/.zshrc; \
  else echo 'export GPG_TTY=$(tty)' >> ~/.zprofile; fi

测试一下

Commit后 会让你输入密码

维护代码的尊严:GPG签名让你的Git commit不再裸奔

提交成功后push,使用git log --show-signature查看一下本地签名信息

维护代码的尊严:GPG签名让你的Git commit不再裸奔

github上看一下这个commit

维护代码的尊严:GPG签名让你的Git commit不再裸奔

对Tag签名

若要对标记进行签名,请将 -s 添加到 git tag 命令。

$ git tag -s MYTAG
# Creates a signed tag

通过运行 git tag -v \[tag-name]\ 验证已签名的标记。

$ git tag -v MYTAG
# Verifies the signed tag

缓存密码

当我们配置完上面的一切以后。 提交的时候, gpg 总会弹出一个密码询问框, 让你输入你创建密钥对时使用的密码, 去解开加密保存的私钥, 从而使用私钥去签名。

修改密码缓存的时间,默认设置的缓存有效时间为600秒,最大支持604800秒。

8小时:28800‬ , 12小时:43200‬ , 24小时 :86400 7天:604800

➜ vim ~/.gnupg/gpg-agent.conf

# copy and save
default-cache-ttl 604800
max-cache-ttl 604800
default-cache-ttl-ssh 604800
max-cache-ttl-ssh 604800

allow-loopback-pinentry

# reset
➜ gpgconf kill gpg-agent && gpgconf --launch gpg-agent

注意 较长的密码缓存时间提供了更多的方便性,因为你不需要在每次 GPG 操作时都输入密码。但这也增加了安全风险,因为其他人在该时间段内可以执行 GPG 操作而无需输入密码。因此,在设置密码缓存时间时,需要综合考虑安全性和方便性,并根据自己的需求进行选择。

常用命令

  • gpg --full-generate-key: 生成密钥对
  • gpg --list-secret-keys --keyid-format LONG: 查看私钥信息
  • gpg --list-keys:查看公钥
  • gpg --delete-secret-key <key ID>: 删除私钥
  • gpg --delete-key <key ID>: 删除公钥
  • gpg --armor --export <email or key-id> > public_key.asc :导出公钥
  • gpg --armor --export-secret-keys <email or key-id> > private_key.asc : 导出私钥
  • gpg -e -r <recipient email or key-id> <file name>: 加密文件
  • gpg -d <file name>.gpg :解密文件