PGP加密电子邮件通信——使用Thunderbird搭配内置OpenPGP收发加密邮件
前言
The natural flow of technology tends to move in the direction of making surveillance easier,
the ability of computers to track us doubles every eighteen months.
----Phil Zimmermann
众所周知,通过互联网传输的的数据很容易被第三方监听和篡改。而我们发送电子邮件时,其数据会通过运营商线路发送到发件人邮件服务提供商的服务器,由服务商的服务器将电子邮件投递到收件人邮箱对应服务商的服务器,最终收件人从服务器上接收邮件。虽然目前绝大多数服务商支持传输过程的TLS加密,这基本杜绝传输中的泄密。但是,邮件原文仍会在双方邮件服务提供商的服务器上留存,这里留下了泄密的风险。如果有一种方案,在发件方发送前本地加密,收件方收到后本地解密,这样就避免了传输过程泄密和篡改。那么如何实现呢?
PGP(Pretty Good Privacy)中文可以翻译成:很不错的隐私。它是一种加密程序,可以为数据通信提供加密和身份验证。PGP可以用于对文本、邮件或文件进行签名、加密和解密。菲尔·齐默尔曼(Phil Zimmermann) 于1991年开发了PGP的最初版本,其最初用户为集权国家持不同政见者、民权主义者和密码朋克的“自由交流”活动家。PGP发布不久,便在美国以外的地方被使用。1993年齐默尔曼被美国政府以“无证出售军火”调查,因为当时美国法律规定大于40位密钥的密码系统被视为"军火",而PGP从未使用低于128位的密钥。菲尔·齐默尔曼以富有想象力的方式挑战了这些规定,他将PGP的源代码通过写成一本书出版了。因为枪支弹药、飞机和软件的出口被限制,但书籍的出口受第一修正案保护。几年后,调查以没有提起任何诉讼而结束。
联邦刑事调查结束后,菲尔·齐默尔曼和他的团队成立了一家公司开发PGP。PGP在随后的几年辗转倒手几家公司,作为一个商业软件,它遇到了一些专利问题,这导致它的使用遇到很多问题。而菲尔·齐默尔曼深信,PGP加密的开放标准对他们和整个加密社区都至关重要。后来IETF应其要求便成立了OpenPGP工作组。后来自由软件基金会开发了一个兼容OpenPGP标准的程序,称为GNU Privacy Guard,简称GnuPG或GPG。
可能有人注意到,在当下,某些对于信息安全比较注意的博主,或是独立调查记者、社会活动家。他们的个人网站电子邮箱附近会留有一个PGP KEY,其后跟着一个40位16进制数。这个数字实际是PGP公钥的指纹,通过它可以在公共PGP公钥分发服务器上找到其对应的完整公钥。有了PGP公钥,我们便可以向其发送加密后的电子邮件了,电子邮件在到达对方的邮件客户端前的整个传送过程,一直都是密文。而除非窃听者获取了对方的私钥,否则无法获取到原文。
Thunderbird是一款开源免费的电子邮件客户端,用于发送,接收和存储电子邮件,分别支持Windows、MacOS、Linux等平台。它目前由开源社区负责维护,它被PRISM BREAK项目所推荐。之前它需要搭配Enigmail插件使用OpenPGP加密,目前Thunderbird 78 原生支持两种加密标准,OpenPGP 和 S/MIME,所以不再需要插件。官方文档描述,Thunderbird 78 OpenPGP标准支持是通过RNP实现的。
实践本文内容前,您可能需要知晓以下内容:
-
准备一个电子邮件账户,需要服务提供商支持IMAP或POP3协议
-
如果对安全要求较高,需确认当前系统无恶意软件
-
如果对数据安全要求极高,建议全盘加密
本文描述的方法用于避免传输过程中邮件内容被窥探,用于证明发件人身份。对于发送前的内容泄密、私钥泄露等皆无力应对;且随着技术发展,此方法并非能够永远安全,请谨慎。
1. 安装Thunderbird并配置邮件账户
-
Thunderbird的安装非常简单。大多Linux发行版都默认安装了它。而在Windows下的安装也非常简单,只需要从官方网站下载适合您语言和系统的安装程序,然后运行安装程序跟随提示安装即可。如果需要修改安装位置可以选择自定义,然后修改安装位置,其他不再赘述。
-
安装完成后运行Thunderbird,会提示您配置邮件账户。如果您关闭了这个窗口,可以点击菜单键(其在主窗口关闭下方,图标是三根横线,下文简称
三横菜单键
),在菜单中点击新建
>已有电子邮件账户...
,打开邮件账户配置窗口。
-
按提示填写发件时显示的名字,电子邮件账户地址,密码,然后点击
继续
。 -
Thunderbird会自带尝试检索邮件服务器配置信息,如果找到,会自动在下方列出。如果检查到的信息与您实际情况相同,可以直接点击
完成
按钮,完成电子邮件账户的添加。 -
如果找不到,或找到的配置信息不正确,您可以点击
手动配置(M)...
按钮,手动填写从邮件服务商处获得的服务器信息。填写无误后点击完成
按钮,完成电子邮件账户的添加。
警告:请确保以上配置中“接收”和“发出”均配置了SSL(安全套接字层)或STARTTLS(启动传输层安全性),这保证您与电子邮件服务商的网络连接是加密的。
注意:如果您电脑系统登录的是公用账户,请不要勾选记住密码。为了数据安全,不建议在公用账户做加密邮件通信。详细参考该官方文档。
注意:某些邮箱,例如网易邮箱、Gmail,可能不再支持使用网页登录的密码连接POP和IMAP服务,需要在网页端按提示生成专用的连接密码。
2. 生成并配置密钥
配置好电子邮件账户后,接下来便是通过内置的OpenPGP密钥管理器生成密钥对。
-
在主界面点击
三横菜单键
>账户设置
,在左侧您的邮箱下的选项中选择端到端加密
,在右侧界面的OpenPGP栏目中点击OpenPGP密钥管理器(K)
按钮以打开OpenPGP密钥管理器。(密钥管理器 也可以从三横菜单键
>工具
中访问) -
点击上方菜单栏中的
生成(G)
>生成新密钥对(K)
,弹出的新建OpenPGP个人密钥窗口。在身份标识处选择您使用的邮箱。密钥到期日建议选择到期时间2年或3年,不建议设置永不过期。密钥类型选择RSA,密钥大小选择4096,点击生成密钥
按钮,在接下来的页面中会询问您是否确定生成,核对无误点击确定等待片刻即可生成密钥对。 -
关闭密钥管理器,此时应该能够在OpenPGP栏目中看到新添加的密钥。点击选中新添加的密钥,即可将该密钥对应用于此电子邮件账户。
可选安全配置:为了更高的安全性,有以下可选项设置,但以下设置会导致易用性下降。
- 禁用远程内容。这个设置在
选项
>隐私与安全
中 ,允许消息中的远程内容
,此选项默认设置就是不启用的。关闭此选项可在一定程度上降低邮件远程内容加载项带来的攻击风险。 - 禁用HTML电邮呈现。打开
三横菜单
,点击查看
>消息体为
(这个翻译太草了) ,此处默认是原始HTML
,将其设置为纯文本
可以更大程度上避免HTML加载项导致的黑客攻击,但会导致大量HTML格式的邮件呈现为几乎不可读的状态。建议只在安全要求极高的情况下使用。 - 禁用HTML电邮撰写。此设置在
账户设置
>通讯录选项
下 。编写
下以HTML格式编写消息
默认为勾选状态。如果要使用纯文本方式撰写邮件,需要把此勾选去掉。 - 启用默认签名与加密。此设置在
账户设置
>端到端加密
下。将发送消息时的默认设置
改为默认要求加密
,勾选默认添加我的数字签名
。这个设置可以避免忘记加密将邮件发出。但会给平时不发送加密邮件的场景带来麻烦,按需启用。 - 将草稿和模板保存在本地。此设置在
账户设置
>副本和文件夹
下,将草稿和模板的保存文件夹设置在本地,而不是邮箱的远程文件夹中,这可避免未完成的、未加密的草稿被自动上传至邮件服务商处,此设置按需配置。
导出私钥:
导出私钥备份到安全的地方可以降低意外导致私钥丢失的情况。私钥丢失将导致您无法解密他人发送给您的加密邮件,这也是一件令人尴尬的事情。同时,Thunderbird中自带的OpenPGP密钥管理器功能有限,后续的发布操作也需要导出到GnuPG完成。
运行Thunderbird,三横菜单键
> 工具
> OpenPGP密钥管理器
。在密钥管理器中选定要导出的项目,然后点击 文件
> 备份私钥为文件
。在弹出的窗口设置保存的位置与文件名称后点击保存,然后在弹出的设置密码窗口中设置密码,最后点击确定完成导出。
注意:此处生成的密钥对包含私钥和公钥。私钥需要安全保存,绝对不共享给其他人。公钥您可以公开分享给信任你的人。具体的使用会在后面的内容中讲述。
3. 加密邮件的发送和接收
要实现加密邮件双向收发,需要双方分别拥有自己的密钥对,并且互相持有对方公钥。这需要一个交换的过程,通常可以将公钥导出,作为附件发送给对方。然后通过电话、线下见面等方式核对公钥的指纹,确保对方收到的公钥没有问题。以下假设Alice和Bob两人要交换公钥。
-
Alice打开OpenPGP密钥管理器,在自己的密钥对上右击,选择
将密钥导出为文件
,选择合适的地方保存,这就是导出的PGP公钥。Alice给Bob发送一个未经PGP加密的邮件,将刚才导出的PGP公钥作为附件发送。此步骤可简化为:Alice打开OpenPGP密钥管理器,在自己的密钥对上右击,选择通过电子邮件发送公钥
。在弹出的邮件撰写窗口中填写Bob的邮件地址并完善标题与正文内容,确定安全选项下为不加密,点击发送即可。
-
Bob收到邮件后,下载附件中Alice的公钥。打开OpenPGP密钥管理器,点击
文件
>从文件导入公钥
,选择Alice的公钥。在弹出的要导入下列密钥吗?的窗口中会显示当前导入公钥的指纹,通过其他可信途径与Alice核实指纹是否正确,核对无误后选择接受
,然后点击确定。在新弹出的成功信息页上点击查看详细信息并管理密钥接受度
,在您是否接受
选项下选择接受,我已验证这的确是正确的指纹
,点击确定键完成设置,然后关闭密钥管理器。 -
Bob完成Alice公钥的导入后,打开OpenPGP密钥管理器,在自己的密钥对上右击,选择
通过电子邮件发送公钥
,在弹出的邮件撰写窗口中填写Alice的邮件地址并完善标题与正文内容,点击安全
右边的下拉按钮,选择要求加密
选项,点击发送即可将公钥和邮件以加密的方式完成发送。而加密后的内容只有Alice的私钥能够解密。 -
Alice收到邮件后,Thunderbird会自动使用Alice的私钥解密邮件内容。Alice下载附件中Bob的公钥,参考步骤2的过程将Bob的公钥导入自己的OpenPGP密钥管理器。到此双方便可以互相发送加密邮件了。结果如下图所示。
还有一种方法是将公钥发布到公钥服务器上,然后双方通过可信的途径交换公钥的指纹。让对方通过指纹或密钥ID来搜索并获取公钥。然后添加时核对指纹,如果没有差异即表示正确的交换了公钥。如何将公钥发布到公钥服务器会在后面内容中讲述。
4. 延长过期密钥
若要延长过期的密钥,在密钥管理器窗口中选择过期的密钥对,右键菜单选择 密钥属性
,然后在打开的窗口中点击更改到期时间
,重新设置到期时间(建议2~3年),密钥对会被更新。之后需要重新与通信伙伴们分享公钥。如果有在公钥服务器上发布,则需要重新发布以更新。
注:该部分笔者没有实际尝试操作,仅供参考。
5. 公钥发布与吊销
上文内容已经实现了PGP加密邮件通信。此处研究一下通过公共密钥服务器发布自己的公钥。这个活单纯靠Thunderbird搞不定,因为它没有这样的功能。为此,我们需要安装一个GnuPGP软件包,因为本文环境为Windows系统,所以需要下载安装Gpg4win。然后使用它将公钥发布到公钥服务器上。
安装Gpgwin:
-
从官网下载Gpg4win安装程序,双击运行安装程序,点击
下一步
。 -
按需要从可选组件中选择要安装的组件,Kleopatra是一个窗口化的密钥管理器,GPA是GNU隐私助理,GpgOL是Outlook插件,GpgEX是资源管理器插件。本文只用到了Kleopatra的部分功能,还有部分操作用命令行淦。选择需要的功能后点击下一步。
-
设置安装位置,建议默认位置即可。然后点击安装,等待其完成安装后退出安装程序。
导入密钥对到GnuPG:
从Thunderbird中导出的私钥文件,在Gnu PG的图形化前端Kleopatra中进行导入。导入后加解密一段任意文本,以触发并完成私钥本身的解密流程。这是一个方法,如果安装了Kleopatra。否则我们也可以在命令提示符中完成。
-
使用以下命令进入备份目录(本例为
E:\Sec\TEST\
),并执行导入。会弹出一个输入密码的对话框,输入之前从Thunderbird中导出时设置的密码,然后点击OK完成导入。C:\Users\Lexsion>E: E:\>cd Sec\TEST E:\Sec\TEST>gpg --import Alice-secret.asc
如图:
成功后有类似以下提示:
gpg: key FFFFFFFFFFFFFFFF: "Alice <Alice@Alice.com>" imported gpg: key FFFFFFFFFFFFFFFF: secret key imported gpg: Total number processed: 1 gpg: imported: 1 gpg: secret keys read: 1 gpg: secret keys imported: 1
-
使用以下命令查看有哪些密钥,记下我们刚导入的密钥对的8位密钥ID,即指纹的后8位(本例为:
67A7B3D5
)。E:\Sec\TEST>gpg --list-keys
部分缩写介绍:
sec => 'SECret key' ssb => 'Secret SuBkey' pub => 'PUBlic key' sub => 'public SUBkey'
-
使用以下命令结合刚才获取到的指纹ID编辑密钥对,将信任等级改为完全信任。完成后退出。
E:\Sec\TEST>gpg --edit-key 67A7B3D5 gpg> trust Your decision? 5 Do you really want to set this key to ultimate trust? (y/N) y gpg> quit
如图:
编辑状态时,usage标记的解释:
Constant Character Explanation
─────────────────────────────────────────────────────
PUBKEY_USAGE_SIG S key is good for signing
PUBKEY_USAGE_CERT C key is good for certifying other signatures
PUBKEY_USAGE_ENC E key is good for encryption
PUBKEY_USAGE_AUTH A key is good for authentication
发布公钥到公共服务器:
我们仍假设8位公钥ID是“67A7B3D5
”,使用以下命令将公钥发布到公共服务器“keys.gnupg.net
”。您也可用发布到其他的服务器,主要的公共密钥服务器之间会定期互相同步的。
gpg --keyserver keys.gnugp.net --send-keys "8D253E8A"
稍等片刻,我们可以尝试用以下命令查询服务器中是否已经有我们的密钥。
gpg --keyserver keys.gnugp.net --search-keys "user-name/e-mail/fingerprint"
撤销公钥:
公钥一旦发布到了公共的公钥服务器上,那便谁都可以获得了。如果哪天我们私钥丢失,无法解密;或是私钥泄露,不再安全怎么办?我们便需要一种机制,可以用来声明公钥已经失效,让大家不要再使用。于是便有撤销公钥的操作,原理便是用私钥签一个公钥回收证书,加入到原有的密钥链中。注意:为了更大程度保证此操作可用,公钥回收证书建议在发布公钥前导出,妥善保管,若需要撤销公钥时直接导入,避免丢失公钥,无法生成撤销证书。
使用以下命令生成回收证书,revoke.asc
为文件名,文件会放在当前操作目录。
gpg --output revoke.asc --gen-revoke "8D253E8A"
使用以下命令将公钥回收证书导入到公钥中。这个操作将在本地撤销公钥,使本地的公钥状态变成已失效(revoked) 。但不会影响已上传到公钥服务器中的数据。
gpg --import revoke.asc
使用以下命令搜索公钥服务器,以确定是否有这个公钥。
gpg --keyserver keys.gnugp.net --search-keys "8D253E8A"
确定服务端有这个公钥的记录之后,使用以下命令上传导入了回收证书的公钥,这样便更新了服务器上的记录。
gpg --keyserver keys.gnugp.net --send "8D253E8A"
稍后我们再使用前面的命令从公共公钥服务器上搜索,便会看到公钥的状态变成了(revoked)。以上即完成了公钥的撤销。
Q&A:
Q:PGP、OpenPGP、GnuPG、GPG、Gpg4win分别是什么,它们有什么关系?
A:相关的问题在前言中有部分提到,PGP是这项技术最早的开发者针对加密程序的命名,目前它是个商业软件,属于赛门铁克(Symantec)。OpenPGP是这项技术的标准,它是商业运作PGP过程中发现专利问题后为了更好发展提出的开放标准。GnuPG全称GNU Privacy Guard,它是自由软件基金会开发的一个兼容OpenPGP标准的程序,其又简称GPG,它是PGP的开源替代品。Gpg4win是一个Microsoft Windows下的软件包,其包含GnuPG核心程序、证书管理器和加密插件。除了OpenPGP作为技术标准名称,其他都是软件名称,他们几乎通用,但支持的加密算法会有不同。
Q:公钥、私钥、指纹、密钥ID分别是什么?
A:公钥用来加密和验证签名,私钥用来解密和签名。指纹是从公钥产生,长度为40位16进制数。密钥ID是公钥的ID,分为长ID和短ID两种,长ID是指纹的后16位,短ID是指纹的后8位。长短ID仅作为方便搜索使用,交换、使用公钥时务必完整核对指纹,避免碰撞攻击。
Q:导出的PGP私钥文件是否包含公钥?
A:导出的PGP私钥文件是包含公钥的,如果你尝试将导出的私钥在其他设备上导入,导入后便能看到其包含公钥。另外,可以使用pgpdump分析私钥文件来研究这个问题。
Q:私钥导出时要求我设置了密码,但是导入时没有提示输入密码就成功导入了?
A:导出私钥时设置的密码是有用的,私钥确实使用您设置的密码加密了。部分GnuPG公钥管理器是这么设计的,导入操作本身是不需要密码的,但是导入后的私钥仍在加密状态,这个状态的私钥是不能使用的。可以使用这个私钥解密一个文件,其会自动提示让您输入之前设置的密码以解锁私钥。本文使用的命令界面操作,没有遇到此问题。
Q:据说其他新的加密算法更加优秀,为什么还要用RSA?
A:为了保证更好的兼容性,所以还是建议选RSA。
Q:POP3和IMAP有什么区别,怎么选择?
A:POP3和IMAP是两种不同的协议,相比IMAP,POP3是一种简单协议。POP3协议将邮件移动到本地,尽管服务商处可以设置将消息保留在服务器上。而IMAP协议是访问、操作远程服务器上的文件夹,下载到本地的被称为副本。IMAP客户端可以对远程服务端的邮件执行各种复杂的操作,它支持通过读写远程服务端的标志以跟踪同步邮件的状态。POP3要求连接到邮件服务器的客户端是唯一 的,IMAP支持多个客户端同时访问。如果需要在多个客户端访问邮件,选择IMAP协议;如果需要邮件接收到本地,不想邮件保存在不受自己控制的服务商那里,选择POP3协议(前提是服务商处的设置确实会在邮件接收后删除邮件,据了解,主流服务商不是这样的,所以推荐IMAP)。
Q:在Android系统下该选择什么邮件客户端?
A:PRISM BREAK项目推荐K-9 Mail,这个应用在GitHub上有开源项目,可以看到完整的源代码。它可以在F-Droid应用市场下载,这个也是闻名的开源Android应用市场。相信开源的项目更让人放心,本人没有尝试过此应用,具体使用方法本文不研究。