GPG(GunPG)的使用

gpg_usage.png
加密的一个简单但又实用的任务就是发送加密电子邮件。多年来,为电子邮件进行加密的标准一直是PGP(Pretty Good Privacy)。程序员Phil Zimmermann特别为电子邮件的保密编写的PGP。这个软件非常好用,迅速流传开来,成了许多程序员的必备工具。但是,它是商业软件,不能自由使用。作为PGP的替代,如今已经有一个开放源代码的类似产品可供使用。GPG(Gnu Privacy Guard),它不包含专利算法,能够无限制的用于商业应用。

环境

  • RHEL7.2
    默认以安装GPG
  • GPG 2.0.22
    libgcrypt 1.5.3

使用方法

生成密钥

使用--gen-key生成一副新的密钥对

1
2
3
4
5
6
7
8
9
10
11
$ gpg --gen-key
gpg (GnuPG) 2.0.22; Copyright (C) 2013 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.

请选择您要使用的密钥种类:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (仅用于签名)
(4) RSA (仅用于签名)
您的选择?

第一段是版权声明,然后让用户自己选择加密算法。默认选择第一个选项,表示加密和签名都使用RSA算法。

1
2
RSA 密钥长度应在 1024 位与 4096 位之间。
您想要用多大的密钥尺寸?(2048)

这一步要让我们输入密钥长度,长度越长越安全,默认为2048。

1
2
3
4
5
6
7
8
您所要求的密钥尺寸是 2048 位              
请设定这把密钥的有效期限。
0 = 密钥永不过期
<n> = 密钥在 n 天后过期
<n>w = 密钥在 n 周后过期
<n>m = 密钥在 n 月后过期
<n>y = 密钥在 n 年后过期
密钥的有效期限是?(0)

如果密钥只是个人使用,并且你很确定可以有效保管私钥,建议选择第一个选项,即永不过期。注意,如果想设置在2年后过期,那么应该输入2y,然后回车 回答完上面三个问题以后,系统让你确认。

1
2
密钥于 日 10/ 8 11:20:32 2017 CST 过期
以上正确吗?(y/n)

到这里,我们对要生成的密钥的配置已经完成了,然后我们还需要一个标识,接下来按照要求依次输入就行了

1
2
3
4
5
6
7
8
9
10
11
12
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>"

真实姓名:Zhang San
电子邮件地址:zhangsan@x163.com
注释:

您选定了这个用户标识:
“Zhang San <zhangsan@163.com>”

更改姓名(N)、注释(C)、电子邮件地址(E)或确定(O)/退出(Q)?

输入o确定,然后在弹出的窗口输入密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动
鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。
.+++++
...+++++
我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动
鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。
....................+++++
...........+++++
gpg: /home/XXXX/.gnupg/trustdb.gpg:建立了信任度数据库
gpg: 密钥 74A64469 被标记为绝对信任
公钥和私钥已经生成并经签名。

gpg: 正在检查信任度数据库
gpg: 需要 3 份勉强信任和 1 份完全信任,PGP 信任模型
gpg: 深度:0 有效性: 1 已签名: 0 信任度:0-,0q,0n,0m,0f,1u
gpg: 下次信任度数据库检查将于 2017-10-08 进行
pub 2048R/74A64469 2016-10-08 [有效至:2017-10-08]
密钥指纹 = 2187 78CA 2E78 83C2 039C E47B D94A 622A 74A6 5569
uid Zhang San <zhangsan@163.com>
sub 2048R/490E5BC8 2016-10-08 [有效至:2017-10-08]

请注意上面的字符串”74A64469”,这是”用户ID”的Hash字符串,可以用来替代”用户ID”。到此为止,我们已经完成了生成公钥和私钥的任务了,文件在/home/XXXX/.gnupg/pubring.gpg

这时,最好再生成一张”撤销证书”,以备以后密钥作废时,可以请求外部的公钥服务器撤销你的公钥。使用--gen-revoke 74A64469进行,此处不再赘述。

查看密钥列表

使用--list-keys列出当前用户已有的密钥

1
2
3
4
5
6
$ gpg --list-keys
/home/zhoub/.gnupg/pubring.gpg
------------------------------
pub 2048R/6058BC49 2017-05-16
uid zhou bo (for coreos build) <zhoubofsy@hotmail.com>
sub 2048R/A47EF901 2017-05-16

第一行显示公钥文件名(pubring.gpg),第二行显示公钥特征(2048位,RSA,Hash字符串和生成时间),第三行显示”用户ID”,第四行显示私钥特征(格式与公钥相同)。
如果你要从密钥列表中删除某个密钥,可以使用delete-key参数gpg --delete-key [用户ID]

输出密钥

公钥导出
公钥文件(.gnupg/pubring.gpg)以二进制形式储存,armor参数可以将其转换为ASCII码显示。gpg --armor --output public-key.txt --export [用户ID]

私钥导出
export-secret-keys参数可以转换私钥

1
gpg --armor --output private-key.txt --export-secret-keys

上传公钥

公钥服务器是网络上专门储存用户公钥的服务器。send-keys参数可以将公钥上传到服务器gpg --send-keys [用户ID] --keyserver hkp://subkeys.pgp.net使用上面的命令,你的公钥就被传到了服务器subkeys.pgp.net,然后通过交换机制,所有的公钥服务器最终都会包含你的公钥。

由于公钥服务器没有检查机制,任何人都可以用你的名义上传公钥,所以没有办法保证服务器上的公钥的可靠性。通常,你可以在网站上公布一个公钥指纹,让其他人核对下载到的公钥是否为真。fingerprint参数生成公钥指纹。gpg --fingerprint [用户ID]

输入密钥

除了生成自己的密钥,还需要将他人的公钥或者你的其他密钥输入系统。这时可以使用import参数gpg --import [密钥文件]

为了获得他人的公钥,可以让对方直接发给你,或者到公钥服务器上寻找gpg --keyserver hkp://subkeys.pgp.net --search-keys [用户ID]
或者

1
2
3
4
5
6
$ gpg --recv-keys E82E4209
gpg: 下载密钥‘E82E4209’,从 hkp 服务器 keys.gnupg.net
gpg: 密钥 E82E4209:公钥“Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>”已导入
gpg: 没有找到任何绝对信任的密钥
gpg: 合计被处理的数量:1
gpg: 已导入:1

加密和解密

使用--encrypt参数用于加密。假设有一个原始文件test.txt

使用公钥(Hash字符串)加密:

1
$ gpg --recipient 74A64469 --output test_en.txt --encrypt test.txt

  • --recipient参数指定接收者的公钥
  • --output参数指定加密后的文件名
  • --encrypt参数指定源文件

使用私钥解密:

1
2
3
4
5
6
7
8
9
10
11
$ gpg test_en.txt

bogon:Desktop XXXX$ gpg test_en.txt

您需要输入密码,才能解开这个用户的私钥:“Zhang San <zhangsan@163.com>”
2048 位的 RSA 密钥,钥匙号 490E5BC8,建立于 2016-10-08 (主钥匙号 74A64469)

gpg: 由 2048 位的 RSA 密钥加密,钥匙号为 490E5BC8、生成于 2016-10-08
“Zhang San <zhangsan@163.com>”
gpg: test_en.txt:未知的后缀名
请输入新的文件名 [test.txt]: test2.txt

签名

有时,我们不需要加密文件,只需要对文件签名,表示这个文件确实是我本人发出的。--sign参数用来签名

1
$ gpg --sign test.txt

然后生成了一个test.txt.gpg文件,我们打开这个文件后,发现这也是一个二进制的数据,这并不是加密后的数据,与上边的二进制数据不一样。
如果想生成ASCII码的签名文件,可以使用--clearsign参数

1
$ gpg --clearsign test.txt

然后生成了一个test.txt.asc文件。
如果想生成单独的签名文件,与文件内容分开存放,可以使用--detach-sign参数

1
$ gpg --detach-sign test.txt

多产生一个,sig的二进制签名文件,如果想采用ASCII码形式,要加上--armor参数。

签名+加密

如果想同时签名和加密,可使用这种格式gpg --local-user [发信者ID] --recipient [接收者ID] --armor --sign --encrypt test.txt

  • --local-user参数指定用发信者的私钥签名
  • --recipient参数指定用接收者的公钥加密
  • --armor参数表示采用ASCII码形式显示
  • --sign参数表示需要签名
  • --encrypt参数表示指定源文件

验证签名

收到别人签名后的文件,需要用对方的公钥验证签名是否为真。使用--verify参数用来验证

1
2
3
4
5
6
gpg --verify test.txt.sig test.txt
gpg: Signature made Wed 17 May 2017 04:12:50 PM CST using RSA key ID 74A64469
gpg: Good signature from "Zhang San <zhangsan@163.com>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 0B77 E327 B365 316D F112 4521 ABC0 9164 6058 BC49

参考&鸣谢