在Emacs中借助GnuPG与Auth-Source保管你的秘密
Table of Contents
- 1. Keeping Secrets in Emacs with GnuPG & EasyPG
- 2. GPG v1 versus GPG v2
- 3. Transparent File Cryptography with EasyPG
- 4. Interactive Commands
- 5. Dired
- 6. Disabling External Pin Entry
- 7. Using Keys to Store Secrets
- 8. Creating a key
- 9. Exporting and Re-Importing a Key
- 10. Encrypting Data with a Key
- 11. Storing Credentials with the Auth Source Package
- 12. Debugging Authentication Issues
- 13. Automatic Jabber Login
- 14. Conclusion
用明文存储机密信息可不好. 如果你非常在意你的机密(若你已经被监控起来了,那么你怎么在意都不过分),那么这篇文章中的建议恐怕还远远不能满足你的需求; 但是对于大多数人来说,用加密的文件来保存机密信息已经足够安全了.
自然,Emacs有多种方式为你加密.
Emacs原生支持GnuPG加密.借助一个名为EasyPG的package(或者缩写为epa)可以对文件进行加签/验证,加密/解密等操作. 我还会告诉你如何使用auth-source这个package(它为不同的加密后端提供了一个统一的接口)来自动登录到各种外部服务上去(需要设置公私密钥).
1 Keeping Secrets in Emacs with GnuPG & EasyPG
GNU Privacy Guard (GnuPG)是OpenPGP标准的一个实现. 它十分的强大,同时支持对称加密与非对称加密. 你可以用它对对二进制文件或归档文件进行签名,用非对称密钥对文件进行加解密,也可以用对称加密的方法对文件进行加密. GPG,你值得拥有.
而且GnuPG也与Emacs整合的很好,Emacs内建了一个名为EasyPG的package,可以提供基本的GnuPG功能.
你即能用EasyPG来对文件加签,也能用它来验签,即能用对文件加密也能用来解密,而且同时支持对称和非对称加解密.
2 GPG v1 versus GPG v2
若你使用EasyPG时发生错误,告诉你找不到gpg程序,那通常是因为你安装的是第二版的GPG,它的文件名是gpg2. 你可以设置一下 epg-gpg-program
的值:
(setq epg-gpg-program "gpg2")
3 Transparent File Cryptography with EasyPG
EasyPG最好用的一个功能是它会在你打开文件时自动解密,然后在保存是自动加密,整个过程对你来说是透明的.
EasyPG package会添加几个hook到Emacs,它会自动地探测一个文件是否为GnuPG加密过的文件. 变量 auto-mode-alist
决定了Emacs打开某个文件时会进入哪个major mode. 在我这,以 .gpg
结尾的文件被认为是经过GnuPG加密过的文件.
你可以测试一下,打开一个文件(例如 /tmp/foobar.gpg
),写入一些内容,在按下 C-x C-s
保存它. 会发现Emacs提示你选择一个密钥来加密,如果你没有选择任何密钥,则会提示你输入用于对称加密的密码.
然后你再重新打开这个文件,会发现Emacs提示你输入上次加密时的密码,然后Emacs会对文件进行解密并打开它.
不仅如此,它还支持嵌套的文件扩展名: 例如打开一个名为 .py.gpg
的文件,Emacs会先对它进行解密然后用普通的python-mode打开它. 对加密过的压缩归档文件也是一样,打开后缀为 .tar.gz.gpg
的文件,Emacs会先解密然后用auto-compression-mode打开它.
4 Interactive Commands
EasyPG有一些方便的快捷键:
Command Description M-x epa-list-keys 列出所有私钥/公钥 M-x epa-list-secret-keysList M-x epa-verify-<region|file> 校验当前region/文件 M-x epa-sign-<region|file> 对当前region/文件加签 M-x epa-insert-keys 在buffer中插入一个或多个密钥 M-x epa-decrypt-<region|file> 解密当前region/文件 M-x epa-encrypt-<region|file> 加密当前region/文件
大多数的命令命名方式都遵照一定模式,并且他们的功能也很直观. M-x epa-list-keys
和 M-x epa-list-secret-keys
都会列出你系统中密钥链中的密钥.
你也可以用Emacs Secrets package (下面会说到)或系统自带的工具(例如Ubuntu的seahorse)来查看这些密钥.
5 Dired
借助Emacs巧妙的auto-mode-alist体系,你可以在Dired中直接打开.gpg文件,跟你在其他地方打开.gpg文件没什么两样. 不过Dired还为EasyPG提供了一些好用的快捷键:
Key Binding | Description |
---|---|
: d | Decrypt marked or selected |
: e | Encrypt marked or selected |
: s | Sign marked or selected |
: v | Signs the current buffer |
如果你mark了多个文件,则Dired会应用命令到这些文件上,否则会应用命令到光标所在的文件上.
要注意:如果你想将多个文件加密成一个.gpg文件,你需要先把这些文件压缩成一个文件:
mark好要被压缩的文件,再按下 c
,然后输入要压缩成的目标文件名. Emacs就会根据目标文件的文件扩展名(.tar.gz, .zip等等)自动选择合适的压缩命令去压缩这些文件,然后你就可以对产生的压缩文件进行加密了.
6 Disabling External Pin Entry
你可以强制让GPG不要用外部工具来读取PIN码. 这在你不希望启用默认的GPG Agent pin entry工具,而希望Emacs来为你管理pin entry时尤其有用.
有很多中方法都能做到这一步(具体的方法跟你的操作系统发行版与窗口管理器有关),不过最简单的在Emacs中禁用agent info的方法是执行下面代码:
(setenv "GPG_AGENT_INFO" nil)
这会强制让Emacs用它自己的内部密码提示功能而不会调用外部的pin entry程序来读取PIN码.
7 Using Keys to Store Secrets
NOTE: 请注意,这只是一篇关于Emacs的博文,而不是专业讲安全的文章. 我们只会列出一些如何在Emacs中使用GPG功能的指导意见.
我之前提到过的,通过对称密码可以透明地加解密文件,操作起来很简单. 但是跟使用非对称加密的方式比较起来还是显得麻烦了一些. 使用非对称密钥加密的好处在于你可以将密钥保存在内存中让Emacs自动加解密文件而无需再次提示你输入密码了.
8 Creating a key
第一步,你需要使用gpg产生一个密钥对:
gpg --gen-key
照者提示一步步下去就能产生密钥了. 我强烈推荐你输入一个密码来保护你的密钥!
你可以通过在Emacs中运行 M-x epa-list-secret-keys
来检查密钥是否加载了.
你也可以在命令行中运行 gpg --list-secret-keys
来检查密钥是否加载了, 这时你可能会得到类似下面的结果:
$ gpg --list-secret-keys sec 2048R/5DB69AC1 2016-06-13 uid Cosmo Kramer (Kramerica Industries) <kramer@example.com> ssb 2048R/02A89A28 2016-06-13
当然你也可以使用类似seahorse这类带界面的程序来检查.
9 Exporting and Re-Importing a Key
第二步,将密钥导出到文件中,需要指定密钥持有人的名称,email地址或密钥的ID:
gpg --armor --export-secret-keys Cosmo Kramer > mykey.asc
现在你可以在别的机器上重新导入这个key了, but you will also have to trust it again. 你可以传递你的全称(放在引号内)或email地址給gpg,它会帮你选择正确的那个key. 下面的例子中我在修改该key传递了密钥持有人的全称进去,gpg会自动帮你找出要修改的是哪个密钥:
$ gpg --import mykey.asc $ gpg --edit-key "Cosmo Kramer" gpg> trust Your decision? 5 Do you really want to set this key to ultimate trust? (y/N) y gpg> quit
现在你已经知道怎么创建一个密钥,也知道如何在不同电脑之间导出/导入密钥了. 但是要注意,若你丢失密钥,则你也就丢失了这些加过密的数据了!
10 Encrypting Data with a Key
你可以告诉EasyPG自动用哪个密钥来加解密. 只需要设置一下文件局部变量 epa-file-encrypt-to that
就行了.
下面是一个简单的例子. 创建一个名为you-secrets.el的elips文件,输入下面内容:
# -*- epa-file-encrypt-to: ("kramer@example.com") -*- (setq jabber-account-list ...) (setq my-secret-password "rosebud")
这里 kramer@example.com
就是我们上面例子中船舰的密钥的email. 这里之所有使用email而不是key ID是因为email更易读一些.
然后执行 M-x epa-encrypt-file
来加密这个文件,并选择上面那个密钥来加密. 下一次你再保存这个文件时,Emacs会自动选择正确的那个密钥并对它进行加密处理.
现在你可以在你的 init.el
中加载这个文件了:
(load-library "/path/to/your-secrets.el.gpg")
Emacs会提示你输入该密钥的保护密码,然后像普通文件那样加载这个elisp文件.
11 Storing Credentials with the Auth Source Package
这部分内容是基于 Using Keys to Store Secrets
之上的.
Auth Source
为各种常见的后端(例如操作系统的Keychain,本地的~/.authinfo和~/.netrc文件)提供了一个统一的接口.
很多Emacs package 都用到了 Auth Source
, 因为它提供了一个很简单易用的API. 这些Package包括 jabber.el, GNUS, TRAMP, 各种内置的网络相关的函数, LDAP (使得Emacs内置了一个LDAP客户端), 以及 ERC.
Auth Source
解决了保存某台主机上用户名与密码的问题,并且它还支持多种后端,允许你将证书存放在多个地方.
12 Debugging Authentication Issues
首先我要提一下有关调试的变量. 在没有添加一个中间层的条件下调试认证问题是很困难的一件事情. 要开启调试信息,需要设置变量 auth-source-debug
, t
表示启用调试信息, nil
表示禁用调试信息:
(setq auth-source-debug t)
这样就会在 *Messages*
buffer中显示很多附加的有用的信息. 请一定记得在调试完后把这个值再设置成nil.
调试时另一个常用的命令是 M-x auth-source-forget-all-cached
. Auth source可能会把你在Emacs中的认证关系搞混乱了,执行这个命令会清空所有的缓存认证信息.
in Emacs; use this command to forget all the cached details.
13 Automatic Jabber Login
下面有一个很常见的工作流: 用jabber.el登录Google Hangouts/Chat.el.
假设有这么一个jabber账户:
(setq jabber-account-list '(("<your-gmail-email>" (:network-server . "talk.google.com") (:port . 443) (:connection-type . ssl))))
当你执行 M-x jabber-connect
后,如果顺利话,Emacs要求你输入密码. 如果你不想每次都输入密码,你可以以加密的方式存储密码并且让Emacs自动为你输入密码.
为了做到这一点,我们需要一个 .authinfo
文件,还要通过某种途径告诉Emacs授权文件的位置. 默认情况下Emacs会尝试 ~/.authinfo
等几个地方,不过我比较推荐对授权文件进行加密并将之纳入源代码管理中.
你可以通过设置变量 auth-sources
的值来告诉auth-source去哪些地方查找授权文件:
(setq auth-sources '((:source "~/.emacs.d/secrets/.authinfo.gpg")))
你需要根据实际情况修改上面的路径. 下一步,创建这个授权文件然后添加下面一行内容:
machine gmail.com login <your account name> port xmpp password <your secret password>
将 <your account name>
替换为你的用户名(只需要用户名,例如是填johndoe而不是johndoe@gmail.com). 将 <your secret password>
替换为你自己的密码,然后保存该文件并选择之前创建的密钥进行加密.
确定已经设置了 auth-sources
变量的值后,再运行一次 M-x jabber-connect
. 如果你的设置无误的话,Emacs会解密你的 .authinfo.gpg
文件(若Emacs没有存储密钥到内存中的话,还会提示你输入你的保护密码),然后根据主机名与用户名从 .authinfo.gpg
文件中找出对应的密码,发送給Jabber.
如果出错了,请参见上面 Debugging Authentication Issues
部分的内容.
同样的,你还可以将这种方法应用于你的email,应用于TRAMP(若没有使用SSH密钥的话)以及其他类似的场景中. Emacs会将密钥存储在内存中并且自动用它来进行加解密,而不会一边又一边的要求你输入保护密码.
另外, auth-sources
变量支持多中校验来源. 你甚至可以可以使用你操作系统中的keychain/agent作为密钥的来源.
14 Conclusion
你的Vogon poetry是安全的,这真是一个好消息. 如你所见,借助GPG以及Emacs的认证机制,可以使得大多数的认证过程变得自动化. EasyPG 与 Auth Sources是两个值得学习的强力工具. 事实上,我这里不过是提到了一点皮毛. 每个人都可能有自己独特的相关配置,所以如果你有什么有趣的,能够节省时间的流程,请告诉我.