签署工作
Git 虽然是密码级安全,但它也不是万无一失的。 如果你从网上的其他人那里拿取工作,并且想要验证提交是不是真正地来自于可信来源, Git 提供了几种通过 GPG 来签署和验证工作的方式。
# GPG 介绍
首先,在开始签名之前你需要先配置 GPG 并安装个人密钥。
$ gpg --list-keys
gpg: /c/Users/Administrator/.gnupg/trustdb.gpg: trustdb created
如果你没安装密钥,可以使用 gpg --gen-key
生成一个。
$ gpg --gen-key
gpg (GnuPG) 1.4.22; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection?
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"
Real name: will
Name must be at least 5 characters long
Real name: will.wang
Email address: willcoder@example.com
Comment: will
You selected this USER-ID:
"will.wang (will) <willcoder@example.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
..+++++
..+++++
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
.........+++++
..........+++++
gpg: key AF53EA1B marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
pub 2048R/AF53EA1B 2020-09-02
Key fingerprint = 62A1 4017 33B5 2A2B 7223 6CC6 9EEE 8AE9 AF53 EA1B
uid will.wang (will) <willcoder@example.com>
sub 2048R/4188B8D3 20
一旦你有一个可以签署的私钥,可以通过设置 Git 的 user.signingkey
选项来签署。
$ git config --global user.signingkey 0A46826A
现在 Git 默认使用你的密钥来签署标签与提交。
# 签署标签
若已设置好一个 GPG 私钥,可使用它来签署新的标签.所需要做的只是使用 -s
代替 -a
即可:
$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "will.wang (will) <willcoder@example.com>"
2048-bit RSA key, ID AF53EA1B, created 2020-09-02
如果在那个标签上运行 git show
,会看到你的 GPG 签名附属在后面:
$ git show v1.5
tag v1.5
Tagger: will <willcoder@example.com>
Date: Mon Sep 2 22:58:56 2020 +0800
my signed 1.5 tag
-----BEGIN PGP SIGNATURE-----
iQEcBAABAgAGBQJfVkqwAAoJEJ7uiumvU+ob6QcH/inTffFD8u6SW0HpdqS0uXPZ
AfjAiYYyHpB9u2/dNS0Z/VDRTq0pHpeG6PMqMirMOQlwPT6lnnHjN5ciI04zQ0Ex
IinPZ9VvleO9/7WxoLPCwZLRGhzGP12F6FMNgMvB9+Fv2UZqb0TESwkJahpthyRV
Pdao7Lo1BqmG9WfkrdQm4S8nP2QyuyWDJQlTjuPKJlRZKeSCU+wPP7aFy7yvnJn1
BvIPBUvjrqPKZTcJF18MJtZZaHTBoDfMoSZS6Z6qgJBmGYBaNH81OwD8dO3UElSu
+f+ypLi68SGrSXgOvuaDjlddzqpn3FVQKfBzcSWY/PlVeKxkJjQHmknROXzm178=
=MkgG
-----END PGP SIGNATURE-----
commit a732e98e0cb8226e9c5e6d22d3ea1c981b986b1d (HEAD -> master, tag: v1.5, origin/master, origin/HEAD)
Author: will <willcoder@qq.com>
Date: Mon Sep 7 22:15:58 2020 +0800
add work
diff --git a/my_Unfinished_Work2.txt b/my_Unfinished_Work2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/my_Unfinished_Work3.txt b/my_Unfinished_Work3.txt
new file mode 100644
index 0000000..e69de29
# 验证标签
要验证一个签署的标签,可以运行 git tag -v <tag-name>
。 这个命令使用 GPG 来验证签名。为了验证能正常工作,签署者的公钥需要在你的钥匙链中。
$ git tag -v v1.5
gpg: Signature made 2020年09月 2日 周三 22:58:56
gpg: using RSA key 9EEE8AE9AF53EA1B
gpg: Good signature from "will.wang (will) <willcoder@example.com>"
object a732e98e0cb8226e9c5e6d22d3ea1c981b986b1d
type commit
tag v1.5
tagger will <willcoder@example.com> 1599490736 +0800
my signed 1.5 tag
如果没有签署者的公钥,那么你将会得到类似下面的东西:
gpg: Signature made 2020年09月 2日 周三 22:58:57
gpg: using RSA key 9EEE8AE9AF53EA1B
gpg: Can't check signature: public key not found
error: could not verify the tag 'v1.5'
# 签署提交
在最新版本的 Git 中(v1.7.9 及以上),也可以签署个人提交。如果相对于标签而言你对直接签署到提交更感兴趣的话,所有要做的只是增加一个 -S
到 git commit
命令。
$ git commit -a -S -m 'signed commit'
You need a passphrase to unlock the secret key for
user: "will.wang (will) <willcoder@example.com>"
2048-bit RSA key, ID AF53EA1B, created 2020-09-02
[master 3b69384] signed commit
2 files changed, 2 insertions(+)
git log
也有一个 --show-signature
选项来查看及验证这些签名。
$ git log --show-signature -1
commit 3b69384a52720f9efcd282f825824171013ee120 (HEAD -> master)
gpg: Signature made 2020年09月 2日 周三 23:06:11
gpg: using RSA key 9EEE8AE9AF53EA1B
gpg: Good signature from "will.wang (will) <willcoder@example.com>"
Author: will <willcoder@example.com>
Date: Mon Sep 2 23:06:11 2020 +0800
signed commit
另外,也可以配置 git log
来验证任何找到的签名并将它们以 %G?
格式列在输出中。
$ git log --pretty="format:%h %G? %aN %s"
3b69384 G will signed commit
a732e98 N will add work
a66ee73 N will unfinishedwork
60434ac N will Subject line (try to keep under 50 characters)
24de949 N will git apply
ea561d5 N will insert
d3c8035 N will git merge
3d0dc48 N wzw-001 delete
d76809c N wangzhenwei update
ca671b5 N will init
这里我们可以看到只有最后一次提交是签署并有效的,而之前的提交都不是。
在 Git 1.8.3 及以后的版本中,git merge
与 git pull
可以使用 --verify-signatures
选项来检查并拒绝没有携带可信 GPG 签名的提交。
如果使用这个选项来合并一个包含未签名或有效的提交的分支时,合并不会生效。
$ git merge --verify-signatures non-verify
fatal: Commit ab06180 does not have a GPG signature.
如果合并包含的只有有效的签名的提交,合并命令会提示所有的签名它已经检查过了然后会继续向前。
$ git merge --verify-signatures signed-branch
Commit 13ad65e has a good GPG signature by Scott Chacon (Git signing key) <schacon@gmail.com>
Updating 5c3386c..13ad65e
Fast-forward
README | 2 ++
1 file changed, 2 insertions(+)
也可以给 git merge
命令附加 -S
选项来签署自己生成的合并提交。下面的例子演示了验证将要合并的分支的每一个提交都是签名的并且签署最后生成的合并提交。
$ git merge --verify-signatures -S signed-branch
Commit 13ad65e has a good GPG signature by Scott Chacon (Git signing key) <schacon@gmail.com>
You need a passphrase to unlock the secret key for
user: "Scott Chacon (Git signing key) <schacon@gmail.com>"
2048-bit RSA key, ID 0A46826A, created 2014-06-04
Merge made by the 'recursive' strategy.
README | 2 ++
1 file changed, 2 insertions(+)