Pages

Sunday, 29 November 2015

使用 GnuPG 实现电子邮件/文件加密和数字签名——PGP简明教程

  • 先阐述最简单和容易实现的操作——邮件加密和签名,着重以图形工具讲解。然后放在第二篇再讲解命令行工具,以及对文件进行加密和数字签名的方法。
http://en.wikipedia.org/wiki/Pretty_Good_Privacy%EF%BC%89" style="box-sizing: border-box; color: #bc360a; text-decoration: none;">PGP (Pretty Good Privacy)
 是由 Phil Zimmermann (之所以提这个名字是因为这位仁兄背后有一段故事,有兴趣可以找找他的八卦)于 1991 开发的一个用于数据加密和数字签名的程序,由于被广泛应用,以至于后来形成一个开放的标准 OpenPGP,这个标准也是目前最为常用的邮件加密和签名的方式。而 GnuPG 则是实现了该标准的一个开源免费程序,本文将会简单介绍如何使用 GnuPG 管理钥匙、加密/解密文件和电子邮件、数字签名文件和电子邮件。篇幅有点长,一共分两章,不过内容是很简单的。@ivarptr

目录:

  • 加密和数字签名的简单原理
  • 下载并安装 GnuPG
  • 使用(图形化)工具管理钥匙
  • 邮件的加密和数字签名
  • 使用命令行管理钥匙
  • 使用命令行加密解密文件
  • 使用命令行对文件进行数字签名
  • GnuPG 的更多指南

一、加密和数字签名的简单原理

首先每位用户都需要用 GnuPG 程序生成地球上惟一的一对钥匙,分别称为公钥和私钥(即 public key 和 private/secret key)。公钥用于加密、私钥用于解密。使用公钥加密过的信息只能由配对的私钥解开。这种加密方式叫做非对称加密。
非对称加密的过程是:如果A君要发送信息给B君,首先B君得把自己的公钥扔出来,A君得获取B君的公钥后用B君的公钥加密信息并发送过去,B君收到(加过密的)信息使用自己的私钥解密就可以还原信息了。
在数字签名时,私钥用于签名、公钥用于核对签名。
数字签名的过程是:如果A君要发送信息给B君,信息首先会被计算出一个指纹值(比如MD5值),然后A君使用自己的私钥加密信息和这个指纹值(这个过程称为签名)并发送出去,接受者B君收到信息之后使用A君的公钥来解密并重新核对一次信息的指纹值,这样B君就可以核对信息有无被篡改以及是否真的为A君所发出的了。

二、下载并安装 GnuPG

GnuPG 是一个集钥匙管理、加密解密、数字签名于一身的工具,对于 Linux 系统,一般可以在系统本身的软件源找到 GnuPG,比如对于 ArchLinux 可以使用如下命令安装:
$ sudo pacman -S gnupg
对于 Windows 系统可以下载免费开源程序包 GPG4Win,建议下载完全版,里面既包含了 GnuPG 命令行工具,又有图形化的钥匙管理工具 Kleopatra 和邮件客户端程序 Claws Mail。对于Mac OSX 系统则可以使用 GPGTools
更多的相关工具可以在这里找到

三、使用(图形化)工具管理钥匙

上一节提到,在不同的平台下所使用的管理工具各不相同,幸运的是他们的功能大同小异,而且界面简单,相信只要你一运行则不用看教程都会使用。下面就提一下使用要点:
[图1] Linux Gnome 桌面环境自带的钥匙管理工具 seahorse
1、生成钥匙对。一般点击“文件”菜单就会找到“新建PGP钥匙”的选项,跟着提示输入你的名字(建议使用你常用的网名)、email地址以及备注(可以不填)就会生成一个属于你自己的钥匙对。期间会提示你输入一个密码,这个密码是用于保护你的私钥,建议使用比较复杂的密码。
2、发布你的公钥。因为你的朋友要发送加密信息给你则必须要先获取你的公钥,所以,作为一个有礼貌的 GnuPG 用户应该先发为敬。Internet上有很多免费的公钥服务器,你可以把你的公钥发布到随便一个服务器,它们之间会自动同步(最长可能需要几小时或者几天)。在管理工具里选定你的钥匙对,然后选择类似“发布”或者“远程-同步”之类的选项即可。在发布的时候工具可能会询问你使用哪个公钥服务器,正如刚才所说的,随便选一个就可以了。
3、获取你朋友的公钥(或者让朋友获取你的公钥)。在管理工具里选择类似“搜索”或者“远程-查找钥匙”,在搜索框里填写对方的email地址或者生成钥匙时所填写的名字,然后点击搜索就可以找到对方的公钥。作为练习,你可以搜索自己的公钥,如果搜索没有结果则可能时因为服务器还没同步,可以过几分钟再试试。或者搜索我的公钥,我公钥的 email 地址为 ivarptr@126.com。点击选中搜索结果,然后再选“导入”即完成。
4、签收(sign)公钥。为了安全起见,获取你朋友的公钥之后,还需要跟对方核对一下这个公钥是否真的为他所拥有(因为可能存在假冒的情况)。核对的方法是选中你朋友的公钥,再选择类似“属性”或者“详细信息”的选项,其中你可以看到这个钥匙的指纹值,你可以通过电话、聊天工具或者email跟你的朋友核对一下,如果指纹值相同,则点击“签收这个钥匙(sign this key)”,这样就表示你正式可用这个公钥了。如果上一步你导入了我的公钥,则看看指纹值是否为“0D24 0A94 A86C 7B83 3F7C 200E 1CAF 0CB0 72E7 5B05“,这个是我钥匙的指纹值,无误的话就可以点击签收了。(补充:为了避免跟“数字签名”这个名词相冲突,这里我把“sign”书写为“签收”,在一些教程里可能会翻译为“签名钥匙”)
好了,下面我们就可以开始邮件加密和数字签名噜。

四、邮件加密和数字签名

实现邮件加密和数字签名一般需要使用邮件客户端软件,现在一般比较完善的邮件客户端工具都内置集成 OpenPGP 的功能,即本身就可以无缝地使用 GnuPG。比如 Evolution、KMail、Mozilla Thunderbird,对于 Windows 和 Mac OSX 系统,我比较推荐 Thunderbird,这也是一个开源免费程序。谷歌告诉我 Windows 下的 Outlook 和 Live Mail 也支持但我没有试验过,如果不行又懒得下载 Thunderbird,那么使用 GPG4Win 附带的 Claws Mail 也是可以的。因为各个邮件客户端的设置大同小异,下面我以 Evolution 为例简单介绍如何设置。
其实关键的设置只有一步,就是关联你的 email 帐号和你的钥匙id。在 Evolution 的帐号属性里,转到 Security 页,在 OpenPGP Key Id 里输入你的钥匙的id(即生成钥匙对时所填写的名字)或者email地址即可。如下图:
[图2] Evolution 的邮件帐号设置窗口
设置就这么简单。然后在每次写 email 时点击菜单的 Options 勾选 OpenPGP 签名或者/以及加密,然后再发送即可。如下图:
[图3] Evolution 的书写邮件窗口
对方收到邮件时,Evolution 会自动检验签名或者自动解密邮件内容。需要注意的是,再发送加密邮件给你的朋友之前,你要先获取他的公钥(见本文第2节)。
小练习:尝试用邮件客户端发送一封签名或者加密过的邮件给我:ivarptr@126.com。
提示1:在签名或者解密时,有可能会弹出一个窗口要求你输入一个密码,这个密码就是生成钥匙对时设置的密码。
提示2:用网易邮箱收取签过名(而未加密)的邮件时可能会显示检验失败,这是因为网易邮箱会在邮件末尾添加附件的下载地址,相当于更改了邮件的原始内容,所以签名检验失败是肯定的。
好了,如果你只需要电子邮件加密和数字签名,这篇教程到此为止了。如果你喜欢折腾以及对 OpenPGP 好奇,点击这里继续阅读本教程的第二章.
from http://web.archive.org/web/20150327150738/http://archboy.org/2013/04/18/gnupg-pgp-encrypt-decrypt-message-and-email-and-digital-signing-easy-tutorial/


简明教程第二部分,简单讲解 GnuPG 命令行工具的使用方法,以及对文件进行加密和数字签名。

五、使用命令行管理钥匙

如果你想深入了解 GnuPG 的操作和原理,那么使用命令行是一个很好的学习途径。基本上,使用命令行管理钥匙的要点跟图形工具的操作是一一对应。

1、生成钥匙对

$ gpg --gen-key
使用上面的命令可以生成地球上惟一的一对钥匙对(注:命令行前的钱币符号是提示符,不用输入),运行后会询问你几个问题,首选是选择钥匙对的算法:
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 就可以了,输入1并回车。然后选择钥匙的长度:
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
默认是 2048 位,直接回车。然后选择钥匙的有效期限:
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)
默认是永远有效的,如果你打算过一段时间就换一把新钥匙,可以在此输入期限,比如输入30表示有效期为30天,数字后面可以加上单位,比如30m表示30个月,30y表示30年。如果你不知道这步有什么作用,则直接回车。然后询问你确定吗?果断输入y并回车。
接下来是填写一些个人信息:
Real name: ivarptr
Email address: ivarptr@126.com
Comment: ivarptr on Twitter
第1行输入你的名字或者平常喜欢用的网名,比如我的是 ivarptr。
第2行输入你的email地址,比如我上面输入的是 ivarptr@126.com。
第3行输入一行备注,备注的作用是进一步标识自己的身份,比如你在姓名一行输入“小明”,为了让你的朋友更确切地知道是哪个小明,你可以输入“你隔壁家的小明”。
这三行信息用于产生一个标识(uid),用来标识这个钥匙对,在下面的命令行里,就可以用名字或者email地址来指定这个钥匙对。
虽然理论上这些信息是可以随意输入,而且也不会有人阻止你这么做,不过当别人拿到你的公钥时可能会搞不清谁对应谁,所以尽量使用别人分辨得清的名字(建议使用你常用的网名)和email地址。信息输入完之后再输入o并回车确定。
因为 GnuPG 的钥匙(包括公钥和私钥)是保存在本机上的,如果有人或者黑客进入你的计算机把你的私钥盗走了,那么你的身份就有可能被冒充的危险。所以接下来你需要输入一个密码用于保护你的私钥。这个密码最好选择一个稍微复杂一些的。
接下来就是等待程序生成钥匙对了,这个过程根可能需要几秒到几分钟时间,期间你可以去忙其他的事情。

2、查看本机钥匙信息

上一步完成后,可以使用如下命令查看本机上的公钥:
$ gpg --list-keys
输出的结果跟下面的类似:
/home/ivarptr/.gnupg/pubring.gpg
——————————–
pub 2048R/72E75B05 2013-04-17 [expires: 2015-04-17]
uid ivarptr (ivarptr on Twitter) <ivarptr@126.com>
sub 2048R/74F0F5F9 2013-04-17 [expires: 2015-04-17]
从中我们可以看到刚才生成的钥匙对的公钥部分,其中:
  • 72E75B05 是这个公钥的id,这个id跟uid都是用于标识这个公钥的,因为uid是用户随便输入的所以会有重复的情况,因此在某些需要明确指定公钥的命令,需要用id而不能用uid表示这个公钥。另外在使用这个id表示一个钥匙时,记得在前面加上”0x”,是零和字母XYZ的X,比如”0x72E75B05″
  • 2013-04-17 是生成这个公钥的时间,后面括号内的是有效期。
在实际应用中,因为要发送加密信息给你的朋友就需要对方的公钥,所以在本机上可能会有多个朋友的公钥,但私钥往往只有一个,也就是自己的私钥。使用下面命令可以查看本机上的私钥。
$ gpg –list-secret-keys

3、导出公钥

为了将自己的公钥扔给他人,你需要把公钥导出成为一个文件:
$ gpg -a --output key.public --export UID
注:你要把其中的 UID 替换成你的名字或者email地址。
其中参数
  • -a 表示输出文本文件格式。默认输出是二进制格式,因为二进制格式不太方便在网络(比如论坛或者博客)上展示,所以推荐文本格式。
  • –output 指定输出文件的名字,你可以更改为其他名字。
  • –export 表示执行输出公钥操作,后面的 UID 为你要输出的公钥的标识。
运行之后会在当前文件夹得到一个 key.public 文件,你可以使用文本编辑器或者 cat 命令查看里面的内容:
$ cat key.public
内容大致如下:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.19 (GNU/Linux)

…………
…………
-----END PGP PUBLIC KEY BLOCK-----
公钥导出之后,你可以通过各种方式把它发送给你的朋友,比如email或者聊天工具。而比较方便的是把公钥发布到公钥服务器。

4、把公钥发布到公钥服务器

公钥服务器用于储存和发布用户的公钥以便相互交流,这些服务都是免费的,GnuPG 默认的公钥服务器是 keys.gnupg.net,你可以在这里找到更多的服务器,一般来说不用指定公钥服务器,随便发布到一个软件默认的就可以了,因为公钥服务器之间会自动同步。你也可以使用浏览器打开它们的网站,然后把你的公钥复制粘贴上去。当然最直接的是通过命令行:
$ gpg --keyserver keys.gnupg.net --send-key ID
注:你要把其中的 ID 替换成你公钥的id。
其中参数:
  • –keyserver 用于指定公钥服务器,没有特殊需求的话是可以省略这个参数的,不过有些 GnuPG 版本可能需要指定这个参数才能正常工作。
  • –send-key 用于指定待发布的公钥的id。
好了,至此你已经学会生成钥匙对以及发布公钥了。

六、使用命令行加密文件

下面我们来做个试验,尝试导入作者的公钥,然后使用该公钥加密一个文件。通过这个试验就可以学会怎样获取他人的公钥并用之加密信息。

1、在公钥服务器搜索作者的公钥并导入到本机

使用如下的命令可以搜索到我的公钥:
$ gpg --keyserver keys.gnupg.net --search-key ivarptr
参数 –search-key 用于指定搜索关键字,可以是uid的名字或者email地址部分。结果大致如下:
gpg: searching for “ivarptr” from hkp server keys.gnupg.net
(1) ivarptr (ivarptr on Twitter) <ivarptr@126.com>
2048 bit RSA key 72E75B05, created: 2013-04-17
Keys 1-1 of 1 for “ivarptr”. Enter number(s), N)ext, or Q)uit >
如果有重名的情况,这里会列出多条记录。你可以输入n并回车把搜索结果浏览个遍。当你看到id和uid都跟你要找的那个吻合时,输入搜索结果前面显示的数字就可以把相应的公钥下载到本机。如上面的搜索结果,按数字1并回车就可以把我的公钥导入到本机。输入q并回车可退出搜索。
注:服务 keys.gnupg.net 背后是一组服务器,它们之间的信息同步需要一定的时间,如果你刚刚提交了自己的公钥,可能不会立即搜索就有结果,只要过一段时间(最长可能要几小时或者几天)就好了。
如果你确切知道要导入的公钥的id,也可以跳过搜索这步而直接使用如下的命令导入:
$ gpg --keyserver keys.gnupg.net --recv-key 0x72E75B05
其中 0x72E75B05 是我公钥的id,如果把它替换成你朋友的公钥id则为导入你朋友的公钥。
导入公钥还有另一种方法:如果我把公钥文件直接发送了给你,你也可以跳过公钥服务器。下面假设我的公钥文件 key.public 已发送给你,你运行如下命令就可以导入我的公钥了:
$ gpg --import key.public

2、核对公钥的指纹值并签收公钥

把对方的公钥导入到本机后,就已经可以用它来加密信息或者用于校验我的数字签名。不过这样每次操作时都会提示公钥不可信,因为虽然你导入了我的公钥,但存在导入冒充者的公钥的可能性。所以你需要进一步跟我核对公钥是否正确,然后签收(sign key)它。
因为公钥有可能出现冒牌货,所以每个公钥里都加入了指纹值,使用下面命令可以查看指纹值:
$ gpg --fingerprint
列出的结果应该有一组如下所示:
pub 2048R/72E75B05 2013-04-17 [expires: 2015-04-17]
Key fingerprint = 0D24 0A94 A86C 7B83 3F7C 200E 1CAF 0CB0 72E7 5B05
uid ivarptr (ivarptr on Twitter) <ivarptr@126.com>
sub 2048R/74F0F5F9 2013-04-17 [expires: 2015-04-17]
其中 “0D24 0A94 A86C 7B83 3F7C 200E 1CAF 0CB0 72E7 5B05” 就是这个公钥的指纹值。你应该通过打电话或者聊天工具等方式询问对方并核对指纹值是否一致,如果吻合的话就说明你取得的是真货了。
注:因为我不可能公布我的电话 :D 所以如果你看到取回来的公钥指纹值跟我博客这篇文章的一致,就可以当作是真货了。当然如果是实际的朋友,一定要亲口核对的。
确定取得的公钥是真货之后,使用如下命令对这个公钥进行签收(sign key):
$ gpg --sign-key ivarptr
运行上面的命令之后它提示你再确认一次指纹值,输入y并按回车确定。
提示,如果发现获取回来的是冒牌货,可以使用如下的命令删除它:
$ gpg --delete-keys ivarptr

3、加密一个文件

使用文本编辑器(比如记事本或者 vim、echo)创建一个名为 message.txt 的文件,里面写上任意一行文字,然后使用如下的命令加密它:
$ gpg -a --output message-ciper.txt -r ivarptr@126.com -e message.txt
其中参数:
  • -a 表示输出文本文件格式。
  • –output 指定输出(即加密后)的文件名。
  • -r 指定信息的接收者(recipient)公钥的uid,可以是名字也可以是email地址。
  • -e 表示这次要执行的是加密(encrypt)操作。
执行完毕之后会在当前文件夹产生文件 message-ciper.txt,这个就是被加密之后的文件。
注:如果你要加密的是一个二进制文件,则可以省略 -a 参数,这样产生的加密文件的体积会小一些。
小练习:现在你可以用 email 把加密后的文件寄给我,或者把里面的内容复制然后粘贴到我博客的评论里,接下来我会解密然后回复你。如果你希望我也以加密的形式回复你,记得同时告诉我你的公钥 id。

4、解密一个文件

现在假设我已经收到你寄过来的加密文件 message-ciper.txt,使用如下的命令解密:
$ gpg --output message-plain.txt -d message-ciper.txt
其中参数:
  • –output 指定输出(即解密后)的文件名。
  • -d 表示这次要执行的是解密(decrypt)操作。
GnuPG 程序会自动使用我的私钥来解密信息,最后得到一个跟原始内容一样的文本文件 message-plain.txt。
至此,你已经学会使用 GnuPG 加密解密文件了。
提示1:导入公钥、核对公钥的指纹值、签名公钥这些操作你只需做一次,以后就可以重复多次使用该公钥加密信息并发送给对方。
提示2:如果你想自己体会整个加密和解密过程,可以用自己的公钥加密信息,然后用自己的私钥解密,只需把上面第3步的命令当中的接收者uid(ivarptr@126.com)更改为自己的uid即可。

七、使用命令行对文件进行数字签名

下面我会签名一个文件,你可以尝试检验一下这个签名。

1、数字签名一个文件的方法A

现在我有一个文本文件 message.txt,使用如下命令即可对它进行数字签名:
$ gpg -a -b message.txt
其中参数
  • -a 表示输出文本文件格式。
  • -b 表示以生成独立的签名文件的方式进行签名。
命令执行完毕之后,会在当前文件夹里产生一个 message.txt.asc 的文件,这个文件即签名。现在我应该把原信息文件 message.txt 连同签名文件 message.txt.asc 一起寄给你,然后你使用如下命令检验:
$ gpg --verify message.txt.asc
如无意外,应该会看到如下两行:
gpg: Signature made Thu 18 Apr 2013 12:35:00 AM CST using RSA key ID 72E75B05
gpg: Good signature from “ivarptr (ivarptr on Twitter) <ivarptr@126.com>”
其中最重要的是 “Good signature” 字样,表示通过检验,否则表示没通过检验(即意味着原信息的内容被篡改或者原信息不是我发出的)。
提示:如果你有多个私钥,在签名时需要加上参数 -u 指定私钥的 uid。

2、数字签名一个文件的方法B

如果不想生成一个独立的签名文件,则还可以用如下的命令进行签名:
$ gpg -a --clearsign message.txt
跟方法A不同的地方是用参数 –clearsign 替代了参数 -b。参数 clearsign 表示将签名和原信息合并在一起,并生成一个新文件。
命令运行后同样会生成一个文件 message.txt.asc,内容如下:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

hello world, my key id is 72E75B05, finger is 0D24 0A94......5B05, check it
out.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)

iQEcBAEBAgAGBQJRbuXuAAoJEByvDLBy51sFaY8IAKKnXX2JGI51mzYSakqvhNnr
iV2JLvokMkvyDuJQGeNDMim5W7P0/df+G4oO45B9b0iFx6DSQwZGeBjEGCXvCURa
uU2fdEqjaSarlrs0d4R1ihol8rCxkZwBYBBPjcvDkVwoVJJYS0zc3OYzMvWhb8mk
Q72wQ0obX5LedUVrauG9OLkvq9aBKONr6Xlkldd133v3gb/Wzjf71CLYcRoJDpze
2XBSkrGS0UxRp3WixJJK8xyfDfI9VHBaXEndCkgQ+Mpfq9nV5XAm3MKcPjlENq4g
xGywHRpnwpW8N22VE6ZFEUFlXrh5C8hZfGaG/EcT21PeAbZYH8RcnYTbJ+s2nZ4=
=lhd6
-----END PGP SIGNATURE-----
你可以复制这段文字然后保存到一个文件里,如 abc.txt,然后使用如下命令进行检验:
$ gpg --verify abc.txt
使用如下命令可以把原始信息提取出来:
$ gpg --output message-original.txt -d abc.txt

八、GnuPG 的更多指南

至此已经讲完 GnuPG 的基本操作了,如果你还想更深入了解它,这里有几篇官方的文档,推荐阅读一下:
另外 wiki 对 OpenPGP 的讲解也很有值得阅读:
还有一些本文未提到但会用得上的命令:
from  http://web.archive.org/web/20150320051424/http://archboy.org:80/2013/05/15/gnupg-pgp-encrypt-decrypt-file-and-digital-signing-easy-tutorial/
---------------------------

用GnuPG进行信息加密和解密


GnuPG是一个用来进行非对称加密的免费软件。先说说什么是非对称加密。传统的加密手段往往是使用同一个密码进行加密和解密。例如你加密时用的密 码是“abc”,则解密时也要使用“abc”才行。这样就存在一个问题,你不能够把一段加密信息发送给你的朋友。试想,如果采用这种加密方式把信息发送给 你的朋友时,你的朋友必须要知道你的密码才能把你的信息解密出来。但你如何保证你的朋友是绝对可靠的呢?也就是说,如果你的朋友把你的密码告诉了别人,你 的密码就不再安全了。

非对称加密采用的是另一种思想。它会给你产生两个密钥,一个称为“公钥”,另一个称为“私钥”。公钥是可以公开的,你尽管把它传给别人;私钥你一定 要保管好不让其他任何人知道。当某人得到你的公钥后,他就可以给你发送加密信息了。具体来说,他把他要发给你的信息用你的公钥加密后发给你,加密的信息只 能用你的私钥去解密。这样,因为世界上除了你以外没有别人知道你的私钥,所以即使别人看到发送给你的加密信息他也无法解密,甚至连发送者本人也不行。因为 他不知道你的私钥。简单说来,就是用公钥去加密;用对应的私钥去解密。想给谁发送加密信息,首先要得到他的公钥。

支持非对称加密的软件有多种,最著名的可能是美国的PGP了,不过它是个商业软件,价格不便宜。对于加密软件,我反对使用破解软件,因为如果信息需 要加密的话,肯定是非常重要的信息,破解软件无法保证加密的安全可靠。因此我建议使用免费开源的GnuPG软件进行信息的加密和解密。

首先去GnuPG的官方网站下载你的操作系统的软件包()。 然后按照安装向导进行安装。有一步是让你选择语言的,建议选择zh_CN – Chinese (simplified),这样会使GnuPG的输出信息为中文。默认的安装目录是C:Program FilesGNUGnuPG,建议把它加入到PATH环境变量中去。因为GnuPG是一个命令行的软件,将安装目录加入PATH后使用会方便得多。

接下来该使用GnuPG来生成你的公钥和私钥了。打开命令提示符,输入gpg –gen-key。GnuPG会提示你 选择密钥的种类,这里选择默认的第一项“DSA 和 ElGamal”,其他两个都只能用于签名而不能用来加密。按回车接受默认选择。接下来让你设置密钥的长度,数值在1024到4096位之间。长度越长, 安全程度越高,但相应的加密和解密时的计算量也就越大。其实即使是最小值1024位,估计用大型计算机去破解的话也得用好几个月的时间。默认长度是 2048位,足够安全了。然后设置你的密钥有效期,按照提示输入,0表示永不过期。后来确认无误后,输入y确定。

接着输入你的姓名、电子邮件和注释。这些信息将用来标识你的身份。然后按O确认。接着设置你的私钥密码。注意这个密码并不等同于你的私钥,它只是用 来保护私钥不会被其他人利用。私钥是一个很大的整数,你通常是不会去记住的。但当你需要用私钥去解密信息时,GnuPG会提示你输入密码,只有密码输对 了,GnuPG才会去读取你的私钥去解密信息。

输入完两次密码后,GnuPG会提示你动动鼠标键盘之类的,以便产生一个“足够随机”的随机数,最终生成一对公钥和私钥。

至此,一对儿密钥已经产生了。你需要把公钥告诉你的朋友。怎么样得到自己的公钥呢?用gpg的–export选项。下面这个命令会输出我的公钥(假定我在上面生成密钥时设定的姓名为“Wang Jinbo”):
gpg –export “Wang Jinbo”
你看到的应该是一大堆乱码,这其实就是公钥。如果希望公钥看起来整齐一些,可以使用-a选项设置输出为ASCII字符:
gpg –export -a “Wang Jinbo”

把上面的输出重定向到一个文件中去,例如wang.key:
gpg –export -a “Wang Jinbo” > wang.key
这样,wang.key这个文件就是我的公钥了,我可以把它放到我的网站上或者通过电子邮件发送给我的朋友们。

如果你得到了我的公钥,如何用它去加密呢?首先你需要导入我的公钥文件。
gpg –import wang.key
这会将我的公钥导入到你的“钥匙环”中。这样以后你就可以用我的公钥给我发送加密信息了。下面是具体的做法。

假设你给我发送的信息是hello.txt这个文件。现在用GnuPG来加密:
gpg -e -r “Wang Jinbo” hello.txt
这会在当前目录下生成hello.txt.gpg这个文件,这个就是就是hello.txt被加密后的结果。你可以用记事本打开看看,应该是一大堆无意义的乱码。然后你就可以把这个文件通过电子邮件发到我的邮箱中去。我收到后,用下面的方法去解密。
gpg -d hello.txt.gpg
GnuPG会提示我输入密码,也就是我在gpg –gen-key中设定的密码。密码输入完后,GnuPG会在屏幕上立刻显示出解密以后的内容。如果被加密的不是文本内容,比如是一个图片,则可以将输出重定向到一个文件中去:
gpg -d hello.png.gpg > hello.png

---------------------------------------

GnuPG 介绍

一、介绍

PGP(Pretty Good Privacy),是一个基于 RSA 公钥加密体系的邮件加密软件。它不但可以对用户的数据保密以防止非授权者阅读,还能对用户的邮件加上数字签名从而使收 信人确信邮件是由该用户发出。让人们可以安全地和从未见过的人们通信,而事先不需要任何保密的渠道用来传递密钥。PGP 采用了审慎的密钥管理,一种 RSA 和传统加密的杂合算法,用于数字签名的邮件文摘算法,加密前压缩等。它功能强大,速度很快。

GnuPG 是实现安全通信和数据存储的一系列工具集,可以做加密数据和做数字签名之用。在功能上,它和 PGP 是 一样的。由于 PGP 使用了 IDEA 专利算法,所以使用 PGP 会有许可证的麻烦。但是 GnuPG 并没有使用这个算法,所以对用户来说使用 GnuPG 没有任何 限制。GnuPG 使用非对称加密算法,安全程度比较高。GnuPG 主要有以下特点:

  1. 完全兼容 PGP
  2. 没有使用任何专利算法,没有专利问题
  3. 遵循 GNU 公共许可证
  4. 与 OpenPGP 兼容
  5. 使用广泛,安全性高于 PGP2,可以加密校验和 PGP5.x 格式的信息
  6. 支持多种加密算法
  7. 支持扩展模块
  8. 用户标识遵循标准结构
  9. 多语言支持
  10. 支持匿名信息接收
  11. 支持HKP密钥服务

一些基本概念:

密钥用途:

  • [S]: 用于签名
  • [E]: 用于加密
  • [A]: 用于身份认证
  • [C]: 主密钥特有,用于认证子密钥

密钥算法

  • RSA
  • ElGamal
  • DSA
  • ECDH
  • ECDSA
  • EdDSA

ECC 算法,在版本 2.1.0 ,支持 ed25519 数字签名,在版本 2.1.7 ,支持 curve25519 加密,需要在操作时时添加参数 --expert,顾名思义,专家模式

二、命令

创建主密钥对
$ gpg --full-gen-key                                # 生成密钥对,默认 RSA 算法
# or
$ gpg --default-new-key-algo rsa4096 --full-gen-key
$ gpg --gen-revoke KEY_ID                           # 为 ID 生成吊销密钥
$ gpg --send-keys KEY_ID                            # 发布公钥
创建子密钥
$ gpg --edit-key KEY_ID     # 假设刚生成的密钥
......
gpg> addkey                 # 根据实际需求选择签名还是加密

一个主密钥对,可以绑定若干子密钥对,子密钥对具备加密或签名功能。任何时候,你应该在非主设备上只使用子密钥对,不应该分发主密钥,你的主密钥应该保存在安全的地方。

显示密钥 ID

$ gpg -K --keyid-form LONG                      # or
$ gpg -K --keyid-format LONG
$ git config --global user.signingkey KEY_ID    # git 中添加签名密钥
公钥处理
$ gpg --armor --output filename.asc --export KEY_ID # ASCII 格式导出公钥
$ gpg --armor --output sub.asc --export SUBKEY_ID!  # 导出 sub ID 子密钥公钥
$ gpg --list-public-keys|-k                         # 显示所有公钥,或
$ gpg --check-sig                                   # 监测公钥环中公钥的签名信息
$ gpg --fingerprint KEY_ID                          # 查看公钥指纹信息
私钥处理
$ gpg --armor --output filename.asc --export-secret-keys KEY_ID         # 导出 ID 的主私钥,不加用户标志,则导出所有主私钥
$ gpg --armor --output filename.asc --export-secret-subkeys SUBKEY_ID!  # 导出 sub ID 的子密钥私钥
$ gpg --list-secret-keys|-K                                             # 显示所有私钥
其他
$ gpg --import filename.asc                 # 导入私钥或公钥
$ gpg --delete-secret-and-public-key KEY_ID # 删除私钥和公钥
$ gpg --delete-secret-key KEY_ID            # 删除私钥
$ gpg --delete-key KEY_ID                   # 删除公钥

$ gpg --edit-key KEY_ID  # 编辑密钥,要帮助输入 help
gpg> help
quit        退出此菜单
save        保存并退出
help        显示此帮助
fpr         显示密钥指纹
grip        显示 keygrip
list        列出密钥和用户标识
uid         选择用户标识 N
key         选择子密钥 N
check       检查签名
sign        为所选用户标识添加签名 [* 参见下面的相关命令]
lsign       为所选用户标识添加本地签名
tsign       为所选用户标识添加信任签名
nrsign      为所选用户标识添加不可吊销签名
adduid      增加一个用户标识
addphoto    增加一个照片标识
deluid      删除选定的用户标识
addkey      增加一个子密钥
addcardkey  增加一个密钥到智能卡
keytocard   移动一个密钥到智能卡
bkuptocard  移动一个备份密钥到智能卡上
delkey      删除选定的子密钥
addrevoker  增加一个吊销用密钥
delsig      从所选用户标识上删除签名
expire      变更密钥或所选子密钥的使用期限
primary     标记所选的用户标识为主要
pref        列出偏好设置(专家模式)
showpref    列出偏好设置(详细模式)
setpref     为所选用户标识设定偏好设置列表
keyserver   为所选用户标识设定首选公钥服务器 URL
notation    为所选用户标识的设定注记
passwd      变更密码
trust       变更信任度
revsig      吊销所选用户标识上的签名
revuid      吊销选定的用户标识
revkey      吊销密钥或选定的子密钥
enable      启用密钥
disable     禁用密钥
showphoto   显示选定的照片标识
clean       压缩不可用的用户标识并从密钥上移除不可用的签名
minimize    压缩不可用的用户标识并从密钥上移除所有签名

* ‘sign’命令可以通过‘l’前缀(lsign)进行本地签名,‘t’前缀(tsign)进行
  信任签名,‘nr’前缀(nrsign)进行不可吊销签名,
  或者上述三种前缀的任意组合(ltsign、tnrsign 等)。

三、应用

加密与解密
$ gpg -r filename.asc -e filename               # 使用公钥文件对 filename 加密,生成二进制 filename.pgp
$ gpg -r KEY_ID -o filename.asc -ea filename    # 同上,不过以 ASCII 方式输入结果,并输出 asc 文件
$ gpg -o filename -d filename.pgp               # 对 filename.pgp 解密,保存为 filename
打包方式进行签名与验证
$ gpg -s filename                   # 使用默认的用户对 filename 进行打包方式的签名
$ gpg -u KEY_ID -s filename         # 使用指定的用户 KEY_ID  对 filename 进行签名
$ gpg --verify filename.gpg         # 验证签名
$ gpg -o filename -d filename.gpg   # 解包并验证签名
分离方式进行签名与验证
$ gpg -sb filename
$ gpg -u KEY_ID -sb filename
$ gpg --verify filename.sig filename
签名并加密
$ gpg -r KEY_ID -es filename                    # 使用指定的公钥进行加密并签名,生成的二进制文件是 filename.gpg
$ gpg -r KEY_ID -o filename.asc -esa filename   # 同上,加上以 ASCII 编码
签名加密时常用参数
 -s, --sign                 # 签名
 -b, --detach-sign          # 分离式签名,文件与签名分开
 -e, --encrypt              # 加密
 -d, --decrypt              # 解密
 -a, --armor                # ascii 编码输出,一般与 -o file 搭配
 -o, --output FILE          # 输出文件
 -r, --recipient USER-ID    # 以特定的 ID 去加密
 -u, --local-user USER-ID   # 以特定的 ID 去签名或解密
作为 ssh 公钥

如果想将 gpg 作为 ssh 公钥,则在创建子钥的时候,需要创建一个 [A] 用途的专用子钥。

编辑 ~/.gnupg/gpg-agent.conf,加入

enable-ssh-support

编辑你的 ~/.bashrc~/.zshrc,加入如下,并最后重新载入下 source ~/.bashrcsource ~/.zshrc,原本写入 ssh-agent 相关的内容,也可以注释掉了

[[ -f /usr/bin/gpg-agent ]] && export GPG_TTY=$(tty)
[[ -n "$SSH_CONNECTION" ]] && export PINENTRY_USER_DATA="USE_CURSES=1"
unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
    export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
fi

编辑 ~/.ssh/config,加入

Match host * exec "gpg-connect-agent updatestartuptty /bye > /dev/null"

获取子钥的 keygrip

$ gpg --with-keygrip --list-key KEY_ID

将对应子匙的 keygrip 插入到 ~/.gnupg/sshcontrol

$ echo xxxxxxyour-keygripxxxxxx >> ~/.gnupg/sshcontrol

重启下 gpg-agent

$ gpg-connect-agent reloadagent /bye

接下来就可以检查下,ssh 验证列表中,是否存在公钥了

$ ssh-add -l

最后将上面的公钥添加到你的远程服务器,或 github 的 gpg 列表中即可

针对 github

如果有多个项目处于 github 的不同账户中,你可能需要针对不同项目配置不同的密钥

gpg --export-ssh-key subkey! > .ssh/repo-1
git config --local core.sshCommand "ssh -i ~/.ssh/repo-1"   # 项目文件夹内执行
mutt 中的使用

复制 mutt 示例配置文件至 mutt 配置目录

$ cp /usr/share/doc/mutt/examples/gpg.rc ~/.mutt/

并在其最后加入

set pgp_autosign=yes
set pgp_replysign=yes
set pgp_replyencrypt=yes
set pgp_sign_as=KEYID       # 你自己的公钥标志 ID
set pgp_timeout=60
set pgp_verify_sig=yes

编辑 ~/.mutt/muttrc,加入如下行

$ source ~/.mutt/gpg.rc

thunderbird 中只需安装 Enigmail 扩展即可,支持 gnupg,可视化的配置就不多说了。

参考:

 

 

---------------------
相关帖子:
https://briteming.blogspot.com/2017/08/gnupgaes.html