PGP (Pretty Good Privacy) 是由 Phil Zimmermann 在 1991 开发的一个用于数据加密和数字签名的程序,一出来就被广泛应用,但是,因为当初创造 PGP 的原因是因为要革一个收费软件的命,所以迫于侵权以及国家安全的压力,后来就形成一个开放的标准 OpenPGP,这个标准也是目前最为常用的邮件加密和签名的方式。而 GnuPG 则是实现了该标准的一个开源免费程序,因为 GPG 的内容有点多,所以本文可能会偏长。

关于对称加密和非对称加密这些基本安全知识本文由于篇幅就不多说了,还不太知道的同学可以在本博客搜索 “对称加密” 自行补充知识。GPG 是一款非对称加密的免费软件,非对称加密方式简单讲就是指用公钥加密文件,用私钥解密文件。如果你想给谁发送加密信息,首先你要得到他的公钥,然后通过该公钥加密后传给他,对方利用自已的私钥就可解密并读取文件了。所以 GPG 运行的机制就是:

  1. 你创建了一对公钥/私钥
  2. 你将公钥发布出公网,随便让人使用
  3. 你使用私钥发布专属于自己的东西,别人通过公钥解密;同时,别人可以通过你的公钥加密给你发信息,你通过自己的私钥解密

GPG 公私钥管理

GPG 是自带公私钥管理的,它会将你的公私钥通过自己的工具管理起来,而你需要通过你的 Key id 来获得公钥或者私钥。默认得,在 ~/.gnupg 目录下,正常有这么几个文件:

  1. ~/.gnupg/gpg.conf 配置文件
  2. ~/.gnupg/trustdb.gpg 信任库
  3. ~/.gnupg/pubring.gpg 公钥库
  4. ~/.gnupg/secring.gpg 私钥库

具体的怎么保存公私钥以及怎么获取公私钥将会在下面讲解

创建公私钥

在命令行中输入命令:

  1. $ gpg --gen-key

然后会提问你一些关于关于公私钥的设置问题,我的设置如下,你可以参考着来:

  1. Please select what kind of key you want:
  2. (1) RSA and RSA (default)
  3. RSA keys may be between 1024 and 4096 bits long.
  4. 2048
  5. Please specify how long the key should be valid.
  6. 0 = key does not expire
  7. Key does not expire at all
  8. y
  9. Real name: liqiang lau !!! 这里记得换成你自己的名字
  10. Email address: liqianglau@outlook.com
  11. Comment: Na
  12. Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
  13. O
  14. gpg: gpg-agent is not available in this session
  15. Enter passphrase: 这里输入你的密码,用于查看公私钥用
  16. 重复输入一遍
  17. Not enough random bytes available. Please do some other work to give
  18. the OS a chance to collect more entropy! (Need 277 more bytes)
  19. 然后随便乱敲键盘,随便输入N多的字符,等待提示

等待很长一段时间之后,你的专属 GPG 公私钥就生成好了,如果一切正常的话,你应该是可以在刚才提到的 ~/.gnupg 目录下看到这些文件的:

  1. ~/.gnupg/gpg.conf 配置文件
  2. ~/.gnupg/trustdb.gpg 信任库
  3. ~/.gnupg/pubring.gpg 公钥库
  4. ~/.gnupg/secring.gpg 私钥库

传播公钥

生成公钥后你可以把公钥中公钥库中导出来,以便传播给需要加密传输信息的人。但是,现在你是不知道你自己的公钥的,因为之前说过, GPG 会将公钥存储在自己的系统中,所以你需要将公钥导出来:

  1. gpg --export --armor liqianglau@outlook.com > gpgkey.pub.asc

这里将 [email protected] 替换成你的邮箱就好了,然后在当前目录你应该会发现 gpgkey.pub.asc 文件,这个就是你的 ascii 格式的公钥。现在,你只需要将这个文件发给任何人了。他们将可以通过这个公钥与你进行私密的通信。

如果你觉得一个一个人发送很麻烦的话,GPG 是有更好的解决办法的,那就是将你的公钥上传到公用的密钥服务器,然后将公钥的ID 和 服务器地址告诉别人就可以了,这样,别人就可以自己去指定的密钥服务器 中下载你的公钥了。当然,别人也可以在没有你告知的情况下通过在密钥服务器中搜索你的邮箱,名字等信息下载公钥。

将公钥上传到密钥服务器

  1. gpg --send mykeyID

这里使用的 密钥服务器 是默认的 keys.gnupg.net,如果你有特殊需要的话,可以指定 keyserver 参数:

  1. gpg --keyserver keyserverAddress --send mykeyID

从公钥服务器上搜索公钥

如果你知道别人的 公钥ID邮箱 或者 名字,你都可以通过 密钥服务器 进行查找:

  1. gpg --keyserver keyserverAddress --search-keys 公钥ID/邮箱/名字

从公钥服务器上下载公钥

如果你找到了你信任的人的公钥,那么你就可以从公钥服务器中下载下来使用了:

  1. gpg --keyserver keyserverAddress --recv-keys 公钥ID

如果别人的直接传给你的公钥文件的话,那么也可以这样导入:

  1. gpg --import gpgkey.pub.asc

其他功能

密钥的导出和导入:以便用来备份密钥或导入到其它机器上。

导出

  1. gpg -oa seckey.asc --export-secret-keys mykeyID

导入

  1. gpg --import seckey.asc

密钥回收:当您的密钥对生成之后,您应该立即做一个公钥回收证书,如果您忘记了您的私钥的口令或者您的私钥丢失或者被盗窃,您可以发布这个证书来声明以前的公钥不再有效。

生成回收证书

  1. gpg --output revoke.asc --gen-revoke mykeyID

导入回收证书

  1. gpg --import revoke.asc

发送回收证书到服务器,声明原 GPG Key 作废

  1. gpg --keyserver keyserverAddress --send mykeyID

列出机器中保存的所有密钥

列出所有公钥

  1. gpg -k

列出所有私钥

  1. gpg -K

加解密使用

非对称加解密
加密:当你导入完好友的公钥后,就可以用朋友的公钥加密文件了

  1. gpg -e -r username filename (-r 表示指定用户)

解密:上面的操作会生成 filename.gpg 加密文件,之后你可以把此文件发送给好友了,对方就可以用自已的密钥来解密文件了。

  1. gpg -d filename.gpg

对称加解密

有时候没有得到对方的公钥,而且资料不是太重要,此时还可以使用简单的对称加密方式(加密及解密都使用相同的密钥/密码),加密过程中提示输出对称密钥/密码,注意:此密码是临时用的密码,不要设置和自己的私钥保护密码一样,以防别人猜测及盗用!

加密

  1. gpg --symmetric filename

解密

  1. gpg -d filename.gpg

签名

数字签名

  1. gpg -o doc.sig -s doc

其中doc是原文件,doc.sig包含了原文件和签名,是二进制的。这个命令会要求你输入你的私钥的密码句。

  1. gpg -o doc.sig -ser name doc 既签名又加密

文本签名

  1. gpg -o doc.sig --clearsign doc

这样产生的doc.sig同样包含原文件和签名,其中签名是文本的,而原文件不变。

分离式签名

  1. gpg -o doc.sig -ab doc

doc.sig仅包括签名,分离式签名的意思是原文件和签名是分开的, b 表示分离式签名detach-sign。

验证签名

  1. gpg --verify doc.sig [doc]

验证之前必须导入文件作者的公钥,对于分离式签名,最后还要加上原文件,即后面的doc。

解疑

  1. 在前面提过 “别人可以在你未告知的情况下从密钥服务器使用你的邮箱搜索你的公钥”,这里有个问题,假设我常用的邮箱是:[email protected],但是,有人用我这个邮箱上传了一个公钥冒充我,而我的朋友通过公钥服务器在没有询问我的情况下认为这个人就是我,那这是不是一个漏洞?

确实,如果单纯得以邮箱搜索公钥确实是不恰当的,因为 GPG 只要你输入邮箱地址即可,并不验证邮箱的有效性以及正确性,也就是说存在这个冒充的风险,但是 GPG 作为这么流行的加密套件,肯定是能解决这个问题的,而解决的方式就是签名

GPG 的解决方法是对公开钥匙签名。每把公开钥匙都有一个相应的用户身份。一个人的公开钥匙可以由别人来签名。这些签名承认这把钥匙确实属于它所声明的信息的用户。那么这样的话,这个公钥的可靠性就取决你对这个对我的公钥进行签名的人有多信任,通过这样的方式你可以知道这个公钥的可靠性。当然,要想绝对确信一把钥匙是正确和真实的,你就得在给予绝对信任之前,通过可靠渠道比较钥匙的”指纹”,例如我在个人主页上暂时的公钥签名(前提还得是我的个人主页没被黑)等等。

Reference