有一天,偶然在 Github 上闲逛的时候,发现某些开发者提交的 Commit 中带着一个绿色的 Verified 标记。好像是某种数字签名,用来表示这个提交确实是该作者贡献的。

细想了一下,估计是为了防止被其他人假冒身份后提交代码而使用的一种验证手段。我们知道 Git 上想要提交代码必须设置自己的“名称”和“邮箱”,但是却无需输入密码。也就是说,有坏心眼的人可以把自己的名称和邮箱设置成和你一模一样,然后用这个身份去其他项目中搞破坏。

环境介绍

首先我自己用的是 OSX,但是我也有一个 Parallels Desktop 的 Windows 7 虚拟机。在 OSX 上的 GPG 签名配置没有碰上什么大问题,所以这里先记录一下在 Windows 下如何让 TortoiseGit 也能支持使用 GPG证书 来对自己的提交进行签名。

这里特别说明一下,虽然“Git for Windows”中自带了一个 gpg.exe 程序,但是他自带的 gpg.exe 版本是 1.4 的,你在 GitBash 中以命令行的方式去使用它,是完全 OK 的。但是如果你想要在带 GUI 界面的 TortoiseGit 中使用 GPG 的话,那么必须使用 gpg.exe 的 2.x 版本(否则会显示no tty等报错),所以我们需要单独再去下载一个 gpg4win 的程序。

操作系统就不用说了,其他的 3 个软件都可以通过搜索得到,这里就不提供下载地址了(部分官网链接资源会放在文章末尾)。

安装软件

这里我假设大家所有的软件都安装在默认目录(TortoiseGit、Git for Windows、gpg4win),如果你的目录自己做过变更,那么后面文章中的路径请自行调整成符合你环境的情况。

对 Git 进行必要设置

以下操作请在 GitBash 中操作(GitBash是安装完成 Git for Windows 后在开始菜单中创建的一个快捷方式,他可以在 Windows 上模拟一个 Liunx 系统的命令行环境,让你可以在里面输入命令)。

如果你安装 gpg4win 的时候采用的是默认路径,那么你应该可以在 ==C:\Program Files (x86)\GNU\GnuPG\== 目录中找到一个名为 ==gpg2.exe== 的文件,请记住他的完整路径。

git config --global gpg.program "C:\Program Files (x86)\GNU\GnuPG\gpg2.exe"

上面的指令用来告诉 git,让他在需要用到 gpg 的时候,去找我们指定路径的 gpg2.exe 程序,而不是使用自己自带的老版本 gpg.exe

git config --global commit.gpgsign true

上面的指令用来告诉 git,让他在每次进行 commit 的时候都要进行 GPG 签名

生成 GPG 证书

接下来,我们需要来生成自己的 GPG证书,这个操作也是在 GitBash 环境下执行的~ 这时候你需要准备一下你的“真实姓名”和“邮件地址”。如果你已经使用过 Git 的话,实际上就是你git程序的 user.name 和 user.email 配置。

比如,我的 Github 账号是 CairoLee 邮箱是 cairoliyu@gmail.com

那么我待会儿生成 GPG 证书时填写的资料中,真实姓名就必须是 CairoLee,邮箱就必须是 cairoliyu@gmail.com 否则的话也会出问题~

如果你是第一次用的话,那么自己想一个“真实姓名”和“邮箱”吧(实际上这里的“真实姓名”不一定需要真实,填写自己的英文昵称就好)。差点忘记说了,真实姓名只能是英文,可以有空格,但是不能有任何中文字符

好了,废话不多是,开始生成 GPG 证书,在 Gitbash 环境中,先确认一下命令行中使用的是不是我们最新安装的 gpg4win 的程序。

gpg2 --version

若能看到“gpg (GnuPG) 2.0.30 (Gpg4win 2.3.1)”类似的字样的话,就说明是正确的。

$ gpg2 --version
gpg (GnuPG) 2.0.30 (Gpg4win 2.3.1)
libgcrypt 1.6.5
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: C:/Users/Sean/AppData/Roaming/gnupg
Supported algorithms:
Pubkey: RSA, RSA, RSA, ELG, DSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

然后开始创建密钥

gpg2 --gen-key

输入上面的指令后,分别作出以下操作:

- Your selection? 直接回车(实际上选择的是 RSA and RSA)
- What keysize do you want? (2048) 这里推荐填写 4096 然后回车
- Key is valid for? (0) 直接回车(证书永不过期)
- Is this correct? (y/N) 按 y 然后回车(确认上面的信息)
- Real name: 输入你的真实姓名,我这里输入 CairoLee
- Email address: 输入你的邮箱地址,我这里输入 cairoliyu@gmail.com
- Comment: 直接回车(这里是描述信息,别填)

最后他会把你输入的信息组合成一个类似:

You selected this USER-ID:
    "CairoLee <cairoliyu@gmail.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?

如果你确认信息的内容是正确的话,就按字母 O 然后回车,然后会提示让你输入证书密码,这里请输入一个你比较常输入的密码吧(因为以后会经常需要用到)

You need a Passphrase to protect your secret key.

此时正常情况下,如果你使用的是 gpg4win 的话,会弹出一个密码设置窗口出来,你在这个窗口中完成设置即可(如果你不用 gpg4win 那么直接在命令行来设置密码)。

成功的话,你会看到如下的信息,这就表示你的证书生成完毕了

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 771F9FFE 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   4096R/771F9FFE 2016-05-24
      Key fingerprint = A2B3 0D30 3902 50B4 A04A  D8D7 52E3 8E44 771F 9FFE
uid       [ultimate] CairoLee <cairoliyu@gmail.com>
sub   4096R/578E8675 2016-05-24

确认你现在有的 GPG 证书公钥列表

gpg2 --list-keys
C:/Users/Sean/AppData/Roaming/gnupg/pubring.gpg
-----------------------------------------------
pub   4096R/771F9FFE 2016-05-24
uid       [ultimate] CairoLee <cairoliyu@gmail.com>
sub   4096R/578E8675 2016-05-24

这里的 “771F9FFE” 这个位置的编号,需要记住,待会儿我们需要用它来生成一大串文本信息,用来填写到 Github 中去。

接下来,确认我们的 GPG 私钥列表

gpg2 --list-secret-keys
C:/Users/Sean/AppData/Roaming/gnupg/secring.gpg
-----------------------------------------------
sec   4096R/771F9FFE 2016-05-24
uid                  CairoLee <cairoliyu@gmail.com>
ssb   4096R/578E8675 2016-05-24

公钥信息和私钥信息的区别主要是开头的3个字母,pub表示是公钥,sec表示是私钥。我们复制一下 “771F9FFE” 这个编号到剪切板。

接下来我们需要告诉 Git 以后提交信息的时候,就用编号为 771F9FFE 的私钥来对 Commit 进行签名。所以我们还需要在 GitBash 上进行如下设置

git config --global user.signingkey 771F9FFE

把上面命令的 771F9FFE 换成你自己看到的编号就可以了~ 这样的话,客户端部分就设置完毕了~

在Github中添加GPG证书

现在你已经完成了客户端的一切必要设置,但是就算你现在去提交 Commit 的话,Github 也不会知道 771F9FFE 这个私钥的拥有者就是 Github 上你的账号的证书。所以你还需要在 Github 上进行一些配置,才可以让 Github 识别出来。

我们现在需要先生成一大串公钥信息,待会儿提交到 Github 的时候,需要用到~ 请在 GitBash 环境中执行以下指令:

gpg2 --armor --export 771F9FFE

成功的话,会返回一大段用“BEGIN PGP PUBLIC KEY BLOCK”开头,以“ND PGP PUBLIC KEY BLOCK”结尾的文本信息,请把它们复制下来(包括“—–BEGIN PGP PUBLIC KEY BLOCK—–”也要复制下来)

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2
...
-----END PGP PUBLIC KEY BLOCK-----

接下来,请登录 Github,然后打开 设置页面,然后在左侧的列表中找到“SSH and GPG keys”,点击进去。紧接着在右侧的页面中,滚动到末尾,点击灰色的“New GPG key”按钮,在文本框中,把刚刚你复制的一整段信息都填写进去,点击绿色的“Add GPG key”按钮,就可以了。

测试一下

现在,你可以用 TortoiseGit 去试图提交信息到一个托管在 Github 上的仓库(提交的时候,应该会提示你输入证书密码),然后再去 Github 上看一下 Commit 记录的话,应该就可以看到你也有 Verified 标记了。

在 macOS 上使用 GPG 签名

在 macOS 若想使用 GPG 签名,需要先安装 GPG Suite,安装完成后才能够在终端里使用 gpg 指令。指令的使用方法和上面提到的 gpg2 类似。

参考文献