/usr/lib/gnupg/gpgkeys_ldap主要程序就是 gpg,用于加密和签名,gpg-zip 用于将文件归档后加密签名。现在 gpg 已经有新的 2.x 版本了,这里主要介绍 1.x。两者差异主要是构架上的,2.x 增加了 agent 来 caching、以及新的协议(X.509),这个我们会在后面慢慢介绍。这里主要介绍一些基本的用法。
/usr/lib/gnupg/gpgkeys_curl
/usr/lib/gnupg/gpgkeys_finger
/usr/lib/gnupg/gpgkeys_hkp
/usr/lib/gnupg/gpgkeys_mailto
/usr/share/man/man7/gnupg.7.gz
/usr/share/man/man1/gpg-convert-from-106.1.gz
/usr/share/man/man1/gpg-zip.1.gz
/usr/share/man/man1/gpg.1.gz
/usr/share/man/man1/lspgpot.1.gz
/usr/share/man/man1/gpgsplit.1.gz
/usr/share/doc/gnupg/THANKS.gz
/usr/share/doc/gnupg/changelog.include.gz
/usr/share/doc/gnupg/faq.html.gz
/usr/share/doc/gnupg/changelog.Debian.gz
/usr/share/doc/gnupg/changelog.po.gz
/usr/share/doc/gnupg/changelog.cipher.gz
/usr/share/doc/gnupg/OpenPGP.gz
/usr/share/doc/gnupg/TODO.gz
/usr/share/doc/gnupg/highlights-1.4.txt.gz
/usr/share/doc/gnupg/FAQ.gz
/usr/share/doc/gnupg/changelog.g10.gz
/usr/share/doc/gnupg/Upgrading_From_PGP.txt.gz
/usr/share/doc/gnupg/changelog.checks.gz
/usr/share/doc/gnupg/changelog.toplevel.gz
/usr/share/doc/gnupg/DETAILS.gz
/usr/share/doc/gnupg/README.gz
/usr/share/doc/gnupg/changelog.tools.gz
/usr/share/doc/gnupg/changelog.util.gz
/usr/share/doc/gnupg/copyright
/usr/share/doc/gnupg/changelog.mpi.gz
/usr/share/doc/gnupg/NEWS.gz
/usr/share/gnupg/options.skel
/usr/bin/gpg
/usr/bin/gpg-zip
/usr/bin/gpg-convert-from-106
/usr/bin/gpgsplit
/usr/bin/lspgpot
/usr/share/doc/gnupg/changelog.gz
为什么要用 gpg 这类程序?其一可以安全的存放自己的数据,通过 gpg 的不对称、对称密钥系统,可以轻松的加密文件。其二作为身份验证的绝佳手段(数字签名),避免身份欺骗。前者,有很多类似的工具,比如 openssl,还有文件系统级别的,那就更加的方便了,但是仍然有些应用,比如邮件,常用的还是 gpg。后者,得益于不对称密钥系统,每个用户产生自己的一堆密钥,保存好私钥,传播公钥。一般来说可以通过密钥的 fingerprint 验证拿到的是否为对方的公钥,还可以通过信任机制,在 keyserver 上获得。
常见的申请出国的同学被黑手写拒信抢了 offer,用好 gpg 这类工具就不会产生这种麻烦(不过要求对方也使用 gpg 验证)。另外很多实时聊天协议并没对传输文本加密,使用 gpg 也能获得这个效果。当然,比较好的是使用签名,如果文本本身并不敏感,避免出现自己机器被其他人使用,冒名顶替。著名的 pidgin 就有一个 pidgin-encryption 插件,可以实现这个功能。常见的有建客户端程序,如 thunderbird、kmail、mutt 都可以方便的使用 gpg。Windows 用户可以使用 gpg,还可以使用商业软件 pgp 以更好的支持诸如 outlook、outlook express 这种软件。
对于开发人员而言,签名还可以作为验证数据完整性的工具,这在发布软件的时候尤为有用
下面就让我们花点时间产生自己的 gpg 密钥,学习如何使用它实现最基本的功能吧。首先看看自己有没有产生自己的密钥,
gpg -k 或者 gpg --list-keys这里列出来的是公钥,公钥一般用来给别人寄送加密文件时(注意公钥只能加密,加密后如果自己没有私钥是无法解密的;这也就是为什么多数邮件客户端寄送加密邮件时会要同时用自己的公钥加密,不然以后自己看自己发送的邮件都不知道是什么了)、或者验证他人签名时使用。如果是想看有没有私钥,则
gpg -K 或者 gpg --list-secret-keys
如果你不曾使用过 gpg,那么很可能两者都没有。这时候我们可以
gpg --gen-key产生自己的密钥对。一般说来 DSA 使用于签名、ElGamal 用于加密,前者长度为 1024 bits,后者最长可以到 4096 bits。建议使用默认的,产生签名和加密的密钥。密钥会对应一个 user ID,通过姓名、电子邮件和备注(可选)确定的,后面我们会发现一个密钥里面可以添加多个 UID 和多个 subkeys,方便用户使用多个帐户、在不同地方使用不同的密钥。产生密钥需要随机数,gpg 会从系统很多地方采集 entropy(比较搞笑的是说使用 gpg --gen-random 产生随机数会降低系统的 entropy),这需要一定的时间。然后用户需要给一个 passphrase 保护密钥(也是 gpg 这个体系的最大弱点之一)。密钥有一个过期时间,这个可以修改,但建议最好是不要修改。我们假设产生的密钥 id 是 12345678(可以用 -k 看到)
密钥产生以后,应尽快制作一个吊销证书,这可以避免一旦密钥失效(如被人窃取、忘记 passphrase 了),可以使用该证书吊销密钥(主要是私钥),吊销而不是删除可以允许你还能访问曾经用该密钥加密的数据(删掉了自己就看不到了),但是程序会拒绝继续使用该密钥签名、加密。这个吊销证书的重要性不言而喻,因此应和私钥分开保存。使用
gpg --gen-revoke 12345678产生一个吊销证书,注意这样调用可能会使得你的屏幕花掉(reset),我们可以通过 --output 指定输出到文件,这会产生 ASCII 输出,因此可以将它打印出来,保存到安全的地方,如保险柜、银行,需要的时候通过 OCR 识别即可。比如
gpg --output someone.revoke --gen-revoke 12345678
那么我们想到的最直接和其他 gpg 用户交互的方法,就是导出自己的 gpg public key,然后寄给对方,让我们在这里共享一下自己的 public key 吧。不过注意,直接
gpg --export 12345678是会花屏的(reset 之),使用 --armor 可以将它变成 ASCII,然后还可以用 --output 啦(后面就不说了)。
当然,私钥也是能导出的,不过如果你的密钥在安全的地方,导出一份到不安全的地方反而不好。后面我们会谈到,可以导出一个 subkey 到其他的地方去用,如果泄露了尽早吊销就好了,不会影响主密钥。
gpg --output someone.sec --export-secret-key 12345678
拿到了别人的公钥后,首先要导入(这部分不存在信任,只是为了处理),然后确定信任关系,才能使用。到入只需要
gpg --import someone.pub即可。那么我们怎么确定我们拿到的公钥就是声称是自己发布的那个人的呢?我们可以通过密钥的 fingerprint,
gpg --edit-key 12345678进入到一个 shell 里面,使用 fpr 命令,我们应该通过绝对可靠的方式验证这个指纹,比如找他当面对比(电话... 其实也不安全的说)。一旦确认了这个,我们就可以信任该密钥了。首先,我们应该对该密钥签名(sign 或者 lsign),然后 check 发现该密钥上除了原来对方自己的签名,还有自己的签名。不过这时没有改变信任关系,仅仅是使得自己可以使用该签名加密了。
加密(-e)和解密(-d)很简单,使用对方的公钥可以
gpg --output file.enc --encrypt file
这会提示添加接受人,也可以用 --receipient 指定。解密需要对应的公钥,直接
gpg --output file --decrypt file.enc即可。加密也可以使用 --armor 产生一个文本文件,体积会比较大;默认情况下会压缩后加密,体积较小。
事实上,也可以直接使用对称密钥(-c)给自己的文件加密,
gpg --output file.enc --symmetric file解密方法与原来一样。
更重要的功能是签名,签名分为几种,一种签名和原文件放在一起,那只需要
gpg --output file.sig --sign file即可,这时一般需要 --decrypt 该文件才能获得原来的文件;只需要验证的话,可以用
gpg --verify file.sig这种签名也会压缩文件,而处理 Email 等文件我们不需要压缩(否则看起来麻烦)。我们选择 --clear-sign,这样就不会改动原文件。另外发布软件的时候,我们也多把签名和发布包分开,这就是所谓的 detached signature,
gpg --output file.sig --detach-sig file验证的时候写两个参数即可,
gpg --verify file.sig file
下面我们看看如何管理我们的密钥,重要的命令是 --edit-key,这将会让我们进入一个 shell,通过各种命令修改我们手中的密钥,比如增加/删除/吊销 UID(对应多个帐号),增加/删除/吊销 subkeys(可以签名或者加密),指定某个 key 对应的 keyserver(后面介绍如何使用 key server 传播自己的密钥),各种 sign(lsign 只能本地使用不能导出,tsign 同是修改信认为 trust,nrsign 使得不能吊销,delsig 删除签名),添加照片(addphoto),expire 设置过期,primary 设置主 UID,设置信任(trust)等。
我们可以把添加之后的这些信息通过 --export 导出,同时用 gpgsplit 分成若干部分,每部分可以用 pgpdump 查看是否是有效的部分。比如
gpg --export-secret-key | gpgsplit -vp prefix然后我们可以取一部分去组成新的 key,这里有一篇文章介绍如何修改 primary key 为 subkey,当然比较暴力了。比较文明的是用 --export-secret-subkey。
我们来看看 trust 的级别,分 full、marginal、none 和 unkown,如果是 trust,那么用户 sign 过的密钥的私钥 sign 过的密钥跟自己 sign 过的等同效力,也就是说相信这个人的朋友一定是你自己的朋友(他不会认错人);marginal 则不然,这只是表示信任当前密钥的有效性(我认识你而已,你认识的未必是我认识的);none 表示就不是有效的密钥;unknown 则表示对此一无所知。通过信任关系,可以形成一个有向图。一般信任规则如下:如果自己 sign 了;自己 trust 的人 sign 了;或者三个以上 marginal 信任的人 sign 了,那么就是有效的。或者在 trust 的有向图上,该人和你的最短距离是不超过 5。
利用这个信任关系,更好的方法是用 key server,这样每个人上传自己的 signature 就可以了。从服务器上下载,
gpg --keyserver serverurl --recv-key keyid或者上传
gpg --keyserver serverurl --send-key keyid
最后提一下一些 frontend,gpg 自己也做了一个叫 gpa(用 gtk+ 写的,不过尚不好用,虽然自称懂得 gpg 的 frontend);GNOME 里面有 seahorse;KDE 里面原来是 kgpg,到了 KDE 4 似乎还有一个 kleopatra。懒得用命令行的人,或者图形界面整合比较方便的人可以玩玩。