在Git中,用户名和邮箱是可以随意配置的,如果有人冒充你的邮箱和用户名,Git是不会做限制的,那如何证明这个修改是你做的?这就用到了数字签名技术。数字签名是密码学的一个应用,利用非对称加密技术(私钥加密、公钥解密)实现对生成的内容的加解密和完整性校验。内容发布者利用工具生成私钥和公钥,公钥可以公开发布,私钥自己保留。git使用这个技术来验证用户的提交和tag是否是发布者生成的,下面我们就讲讲如何实现git的签名操作。
准备
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
## install gpg sign tools
brew install gpg
## list all keys
gpg --list-keys
## generate new key signing git
gpg --gen-key
## env for git signing
echo 'export GPG_TTY=$(tty)' >> $HOME/.zshrc
export GPG_TTY=$(tty)
## always signing the commit
git config --local commit.gpgSign true
git config --local tag.gpgSign true
|
## install gpg sign tools
brew install gpg
## list all keys
gpg --list-keys
## generate new key signing git
gpg --gen-key
## env for git signing
echo 'export GPG_TTY=$(tty)' >> $HOME/.zshrc
export GPG_TTY=$(tty)
## always signing the commit
git config --local commit.gpgSign true
git config --local tag.gpgSign true
签名
1
2
3
4
5
|
## manually sign the commit by '-S' option
git commit -S -m "fix: tcp port doesn't work"
## manual sign the tag by '-s' option
git tag -s v1.1 -m "v1.1 released by ticktechman"
|
## manually sign the commit by '-S' option
git commit -S -m "fix: tcp port doesn't work"
## manual sign the tag by '-s' option
git tag -s v1.1 -m "v1.1 released by ticktechman"
查看
可以通过下面的命令查看一个提交是否经过签名(高亮行):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
git log --show-signature
commit ba42494e77d8c9a659f1c3d960d15288e494104d (HEAD -> master, tag: v1.5)
gpg: Signature made Thu Apr 25 10:57:08 2024 CST
gpg: using EDDSA key D4D109F096BF6819D45569501C8045609E0B167C
gpg: Good signature from "ticktechman <geek.wystan@gmail.com>" [ultimate]
Author: ticktechman <geek.wystan@gmail.com>
Date: 2024-04-25 10:57:08 +0800
fix
git log --pretty="%h %G? %ad %an - %s"
63da52a N 2024-04-26 15:16:44 +0800 ticktechman - unsigned commit
ba42494 G 2024-04-25 10:57:08 +0800 ticktechman - fix
803ed47 G 2024-04-25 10:51:34 +0800 ticktechman - sign
|
git log --show-signature
commit ba42494e77d8c9a659f1c3d960d15288e494104d (HEAD -> master, tag: v1.5)
gpg: Signature made Thu Apr 25 10:57:08 2024 CST
gpg: using EDDSA key D4D109F096BF6819D45569501C8045609E0B167C
gpg: Good signature from "ticktechman <geek.wystan@gmail.com>" [ultimate]
Author: ticktechman <geek.wystan@gmail.com>
Date: 2024-04-25 10:57:08 +0800
fix
git log --pretty="%h %G? %ad %an - %s"
63da52a N 2024-04-26 15:16:44 +0800 ticktechman - unsigned commit
ba42494 G 2024-04-25 10:57:08 +0800 ticktechman - fix
803ed47 G 2024-04-25 10:51:34 +0800 ticktechman - sign
上面是两种查看commit是否已经签名
- 第一条命令:
gpg: Good signature from "ticktechman <geek.wystan@gmail.com>"
表示这是一个签名过的commit,并且验证通过。
- 第二条命令:第二列中为
G
表示已经签名,N
表示未签名;
验证
1
2
3
4
5
6
|
## verify a commit
git verify-commit HEAD
## verify a tag
git verify-tag v1.1
git tag -v v1.1
|
## verify a commit
git verify-commit HEAD
## verify a tag
git verify-tag v1.1
git tag -v v1.1
关于公钥
公钥支持导出和导入操作,导出是将自己的公钥导出,一般用于上传到keyserver或者通过邮件发送给需要的用户,导入用于将别人的公钥导入到自己本地钥匙串中,用于验证别人的签名是否正常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
## show public key information
gpg --armor --export your-username@abc.com
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEZinD9RYJKwYBBAHaRw8BAQdAKRhZGICa32pnqXwvz516dvBwe1b2GTfRgfSY
jHRP+Am0I3RpY2t0ZWNobWFuIDxnZWVrLnd5c3RhbkBnbWFpbC5jb20+iJkEExYK
AEEWIQTU0Qnwlr9oGdRVaVAcgEVgngsWfAUCZinD9QIbAwUJBaOagAULCQgHAgIi
AgYVCgkICwIEFgIDAQIeBwIXgAAKCRAcgEVgngsWfNH6AQDXsmDGyEgLtLuCD86v
hvpOdYzryJM1kXsdPTPDT1ggiwEA9q3iFqKWhAcMgX9T9TL3zbDmiQttnweHQr/6
bC0swQu4OARmKcP1EgorBgEEAZdVAQUBAQdANiqCf1iu4fMtpT6EFZQR+zUzK8Gy
nODRoTSmAcuAWCUDAQgHiH4EGBYKACYWIQTU0Qnwlr9oGdRVaVAcgEVgngsWfAUC
ZinD9QIbDAUJBaOagAAKCRAcgEVgngsWfMA2AQDr+UGOimeVgLJRZzyfvk6aq2tG
3PBt+tlxznQsUZmgrwD/dtqff1AeXJZZrnb5QuMTrlzkZDMDHeNgHA6fZyRwKgc=
=zH2u
-----END PGP PUBLIC KEY BLOCK-----
## export public key to a file
gpg --output your-username.gpg --export your-username@abc.com
## import a public key from a file
gpg --import <public-key-file>
|
## show public key information
gpg --armor --export your-username@abc.com
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEZinD9RYJKwYBBAHaRw8BAQdAKRhZGICa32pnqXwvz516dvBwe1b2GTfRgfSY
jHRP+Am0I3RpY2t0ZWNobWFuIDxnZWVrLnd5c3RhbkBnbWFpbC5jb20+iJkEExYK
AEEWIQTU0Qnwlr9oGdRVaVAcgEVgngsWfAUCZinD9QIbAwUJBaOagAULCQgHAgIi
AgYVCgkICwIEFgIDAQIeBwIXgAAKCRAcgEVgngsWfNH6AQDXsmDGyEgLtLuCD86v
hvpOdYzryJM1kXsdPTPDT1ggiwEA9q3iFqKWhAcMgX9T9TL3zbDmiQttnweHQr/6
bC0swQu4OARmKcP1EgorBgEEAZdVAQUBAQdANiqCf1iu4fMtpT6EFZQR+zUzK8Gy
nODRoTSmAcuAWCUDAQgHiH4EGBYKACYWIQTU0Qnwlr9oGdRVaVAcgEVgngsWfAUC
ZinD9QIbDAUJBaOagAAKCRAcgEVgngsWfMA2AQDr+UGOimeVgLJRZzyfvk6aq2tG
3PBt+tlxznQsUZmgrwD/dtqff1AeXJZZrnb5QuMTrlzkZDMDHeNgHA6fZyRwKgc=
=zH2u
-----END PGP PUBLIC KEY BLOCK-----
## export public key to a file
gpg --output your-username.gpg --export your-username@abc.com
## import a public key from a file
gpg --import <public-key-file>
- 第一个命令:显示公钥内容
- 第二个命令:导出公钥到一个文件中
- 第三个命令:导入一个公钥到本地钥匙串中
参考:gpg架构图
这是一张GPG工作流程图:
- 用户A使用gpg工具在本地生成钥匙对(公钥和私钥)
- 然后将公钥导出
- 通过gpg命令将公钥发布,可以发不到一个keyserver,也可以通过email发送给需要人
- 用户B从keyserver下载公钥或者通过email接收公钥文件
- 用户B通过gpg工具将用户A的 公钥导入到本地钥匙串中
- 之后用户B就可以对用户A生成的内容进行验证了。
上面的keyserver可以自建,或者使用免费开放的公共服务(不建议使用)
可以用于自建keyserver的资源
目前免费的keyserver公共资源有: