加密的一个简单但又实用的任务就是发送加密电子邮件。多年来,为电子邮件进行加密的标准一直是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 | gpg --gen-key |
第一段是版权声明,然后让用户自己选择加密算法。默认选择第一个选项,表示加密和签名都使用RSA算法。1
2RSA 密钥长度应在 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
12You 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 | gpg --verify test.txt.sig test.txt |