GnuPG 技巧
您是否曾想过使用密码学,却发现它过于复杂?复杂的软件包、密码、密钥、密钥环、证书和指纹是否让您望而却步?
您不需要所有这些。无需任何先前的经验,也无需记住任何东西,GnuPG 即可进行基本且立即可用的密码学操作。GnuPG 甚至可能已经安装在您的 Linux 系统上。
GnuPG 是 GNU 项目对 OpenPGP 标准的实现。它也被称为 GNU 隐私卫士,是一个复杂的公钥密码系统,具有 70 多个命令行选项,以及一个内部命令行和菜单环境。它已被移植到多个操作系统,并可从 GnuPG 网站(见在线资源)获得预编译的二进制文件。与所有 GNU 软件一样,它可以根据 GNU 通用公共许可证免费使用。
OpenPGP 标准 RFC 2440 基于 Phil Zimmermann 于 1991 年开发的 Pretty Good Privacy 系统。OpenPGP 也是更多操作系统上商业产品的基础。OpenPGP 系统是您将遇到的最常见的文件加密系统。
首先,让我们从一些不需要密码的 GnuPG 功能开始。之后,我们将选择一个密码并用它来加密一些东西。请注意,GnuPG 是软件的名称,但命令的名称是gpg.
确保 GnuPG 已安装并在您的路径中
gpg --version
您应该得到类似这样的结果
gpg (GnuPG) 1.4.1 Copyright (C) 2005 Free Software Foundation, Inc. This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. See the file COPYING for details. Home: ~/.gnupg Supported algorithms: Pubkey: RSA, RSA-E, RSA-S, ELG-E, DSA Cipher: 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512 Compression: Uncompressed, ZIP, ZLIB, BZIP2
版本号、日期和其他详细信息可能有所不同。本文中显示的示例应适用于大多数当前和未来的 GnuPG 版本。
现在,输入
gpg /dev/null
您可能会得到类似这样的结果
gpg: /home/you/.gnupg: directory created gpg: new configuration file `/home/you/.gnupg/gpg.conf' ↪created gpg: WARNING: options in `/home/you/.gnupg/gpg.conf' ↪are not yet active during this run gpg: keyring `/home/you/.gnupg/secring.gpg' created gpg: keyring `/home/you/.gnupg/pubring.gpg' created gpg: processing message failed: eof
这是您首次运行 GnuPG 时的正常现象。如果未发生这种情况,则表示您之前已运行过 GnuPG,或者您的 .gnupg 目录已存在。
大多数电子邮件程序都支持文件附件,但命令行电子邮件程序(如 /bin/mail)则不支持。有时,将所有数据保存在消息正文中更方便。但是,二进制文件必须进行 ASCII 编码,以防止在传输过程中损坏。
您可能尝试过使用 uuencode,但发现它令人困惑或无法正常工作。并非所有系统都具有命令行 MIME 编码器。但是,GnuPG 具有与 MIME 非常相似的 ASCII 编码选项,但没有所有的复杂性、开销和功能。
要将文件包装在 PGP ASCII 盔甲中,请输入
$ gpg --enarmor < filename.bin > filename.txt
要解开已在 PGP ASCII 盔甲中的文件,请输入
$ gpg --dearmor < filename.txt > filename.bin
警告:尽管名称如此,OpenPGP ASCII 盔甲绝对没有安全性。如果您确实需要安全性和数据压缩,请参阅下面的“快速简洁加密”部分,并使用好的密码。
您是否怀疑刚收到的文件已损坏?传统上,在发送文件前后,会分别对文件运行sum或cksum命令,并比较输出结果。但是,这些命令有三个不同的不兼容版本,即使是同一版本,由于处理器字节序问题,在不同的机器上也会产生完全不同的输出。更糟糕的是,有时它们甚至无法检测到损坏的文件。仅凭偶然性,即使它们兼容,有时也会为不同的文件产生相同的输出。sum 和 cksum 命令的 32 位输出太小,无法保证可靠性,更不用说安全性了。流行的 SSH v1 CRC-32 补偿攻击也存在相同的漏洞。
您可以改用md5sum,但此命令也有不同的版本。每个版本在文件名、空格和十六进制大小写的格式上都略有差异。这些格式上的差异会阻止diff干净地运行。此外,md5sum 使用的 MD5 哈希算法中存在已知的安全漏洞。而且,有时甚至未安装 md5sum。
GnuPG 避免了这些问题,因为它产生的输出与操作系统或处理器架构无关。GnuPG 还支持更新、更安全的算法
$ gpg --print-md sha1 filename filename: E83A 42B9 BC84 31A6 6450 99BE 50B6 341A 35D3 DCEB
它也接受多个文件
$ gpg --print-md sha1 *.txt test.txt: E0D6 3F44 4253 CED5 9205 4047 4AA6 4E0F FD0F 130D test2.txt: 32AC 34F9 B7AF 1972 C015 E5EE 456E 89BD CC3C 7246
如果您仍然需要 MD5,也可以使用
$ gpg --print-md md5 filename filename: 26 E9 85 5F 8A D6 A5 90 6F EA 12 12 83 C7 29 C4
更新版本的 GnuPG 还支持更安全的哈希算法,例如 SHA-512
$ gpg --print-md sha512 filename filename: FC37410D 9336DD60 22AEB6A2 A42E82F1 2EA3470D 4982E958 B35C14A0 CF381CD2 3C4CBA35 BE5F11CB 05505ED2 DBF1C7A0 397EFF75 007FAEBB 30B43B30 6514990D
顺便说一下,您可以通过创建一个名为 filename 的文件来验证这些 --print-md 示例,该文件包含单行The Linux Journal.
如果文件内容相同,您的哈希值应与本文中的十六进制值完全相同。
想要加密文件,但不知道从哪里开始?这是一个使用 GnuPG 进行文件加密的快速简洁入门指南
$ gpg -c test.txt Enter passphrase: Repeat passphrase:
加密时,GnuPG 会要求输入两次密码,就像您设置新密码时一样。新的加密文件具有相同的名称,但添加了 .gpg 扩展名。原始文件保持不变。
-c 代表传统加密,也称为对称加密。通常,GnuPG 默认使用公钥加密,但我们尚未生成或加载任何公钥,因此目前我们必须坚持使用传统加密。
如果您只想解密自己的文件,但不信任文件的存储位置,则此类型的加密最有用。例如,容易丢失或被盗的存储可以使用此类型的加密进行保护。这种类型的加密对于异地备份尤其有用。
要提取加密文件,只需输入
$ gpg filename.gpg
GnuPG 会自动检测到该文件已使用密码加密,并要求输入该密码。然后,它将解密后的数据写入一个文件,该文件具有相同的名称,但不带 .gpg 扩展名。与加密一样,加密文件保持不变。如果您希望将输出文件写入不同的文件名,请使用标准重定向,就像 --dearmor 示例一样。请注意,必须同时使用输入和输出重定向,否则 GnuPG 会感到困惑
$ gpg < filename.gpg > filename.txt
如果您希望其他人解密该文件,则必须将密码告知此人,而不要将密码泄露给任何其他人。一种简单直接的方法是当面告知。这似乎不是很有用,因为原始文件也可以当面交付。但是,该密码现在可以在将来安全地多次重复用于不同的文件。但是,与密码一样,密码也应定期更改。除非您希望他们解密您使用该密码加密过的所有文件,否则切勿与其他人重复使用密码。
注意:在 GnuPG 中使用密码加密时,此警告是正常的。公钥加密可以避免这种情况
gpg: WARNING: message was not integrity protected
密码是保护其他秘密的秘密,这使其成为 GnuPG 安全性最重要的部分。不幸的是,在实践中,密码也是薄弱环节。这是因为创建好的密码很困难,而记住它们则更加困难。
我强烈推荐 Diceware,但如果它不吸引您,请查看 Wikipedia 文章(请参阅“资源”)或您喜欢的 Web 搜索引擎推荐的密码网页。
无论您选择哪种方法,密码安全的简单指南是,通常越长越好(表 1)。
表 1. 密码和密码强度与估计破解时间比较。
类型 | 长度 | 位 | 总位数 | 破解时间 |
---|---|---|---|---|
任何语言的单个词 | 8 个字符 | 24 | 24 | 秒 |
随机单字母大小写字母 | 8 个字符 | 4.7 | 37 | 分钟 |
随机单字母大小写字母 | 16 个字符 | 4.7 | 75 | 十年 |
base64 [A-Za-z0-9+/=] | 10 个字符 | 6 | 60 | 月 |
base64 [A-Za-z0-9+/=] | 20 个字符 | 6 | 120 | 无法破解? |
完全随机的可打印字符 | 6 个字符 | 6.5 | 40 | 分钟 |
完全随机的可打印字符 | 8 个字符 | 6.5 | 52 | 小时 |
完全随机的可打印字符 | 12 个字符 | 6.5 | 78 | 十年 |
完全随机的可打印字符 | 15 个字符 | 6.5 | 97 | 世纪 |
完全随机的可打印字符 | 20 个字符 | 6.5 | 130 | 无法破解? |
Diceware 密码 | 2 个词 | 12.9 | 26 | 秒 |
Diceware 密码 | 4 个词 | 12.9 | 51 | 小时 |
Diceware 密码 | 6 个词 | 12.9 | 78 | 十年 |
Diceware 密码 | 8 个词 | 12.9 | 120 | 无法破解? |
表 1 中的时间估计范围很广,因为金钱和时间可以均匀地交易。计算能力不断变得更便宜,因此破解时间不断缩短。破解成本从免费开始,然后上升。
如果您无法记住 GnuPG 密码,则使用该密码加密的数据可能永远丢失。GnuPG 中没有已知的后门,也没有任何方法可以恢复丢失的密码,除非猜测。所需时间长短取决于密码的强度。一个好的 20 个字符的密码可能需要数十亿年的时间才能猜到,即使使用所有当前和未来的计算机也是如此。
这是一个使用 GnuPG 本身生成非常安全的密码的快速技巧。该密码不容易记住或键入,但它将非常安全。该技巧使用 GnuPG 生成 16 个随机二进制字节,然后再次使用 GnuPG 将其转换为 base64。最后的 sed 命令会剥离标头,留下可用作密码的单行
gpg --gen-random 1 16 | gpg --enarmor | sed -n 5p
不要使用 gzip 来压缩 tarball,而要使用 GnuPG。tarball 的最终大小将大致相同,但它们也将被加密。顺便说一下,不要费心尝试 gzip 或以其他方式压缩任何加密文件。加密数据通常是不可压缩的。这是因为数据压缩和加密在数学上密切相关。因此,大多数密码系统(包括 GnuPG)都会在加密前自动压缩。压缩还可以略微提高安全性。
系统将提示您输入两次密码,就像之前加密时一样
tar -cf - these files here | gpg -c > these-files-here.tgp
要提取文件,请输入上面输入的密码
gpg < these-files-here.tgp | tar -xvf -
如果您想在脚本中使用 GnuPG,并且不想被提示输入密码,请将密码放在名为 passphrase.txt 的文件中,并使用此命令进行加密
[$ cat passphrase.txt | gpg --passphrase-fd 0 -c < filename.txt > filename.gpg
注意:解密几乎相同,只需删除 -c 并切换文件即可
$ cat passphrase.txt | gpg --passphrase-fd 0 < filename.gpg > filename.txt
如果您要通过电子邮件发送加密文件(可能用于异地备份),请添加 -a 选项以启用 ASCII 盔甲。最终效果与之前使用的 --enarmor 相同,但它包括加密。这也比 uuencoding 或 MIME 产生的文件更小,因为默认情况下,GnuPG 会在加密前压缩数据。
为了完成该技巧,我们还同时通过邮件发送加密文件。请注意使用 -o - 强制 GnuPG 的输出到 stdout
$ cat passphrase.txt | gpg --passphrase-fd 0 -ac -o - filename.txt | mail user@example.com
顺便说一下,将密码放在文件中可能非常危险。任何获得该密码文件副本的人都可以解密它曾经加密过的任何文件。有人甚至可以使用相同的密码创建新文件,从而导致安全且无法检测到的伪造。确保您的密码文件(实际上是整个计算机)具有您期望的安全性。
自动化任务本质上需要将人排除在循环之外,因此这种安全漏洞很难避免。但是,GnuPG 甚至可以通过使用公钥加密来提供帮助。
您是否有一个 OpenPGP 加密文件,但没有密钥环,也不知道如何处理它?也许有人向您发送了一个加密文件,并假设您会知道该怎么做。也许他或她也不知道该怎么做。
如果文件具有 .pgp 或 .gpg 扩展名,您可以尝试使用 GnuPG 解密它。此外,请使用文本编辑器检查文件,看它是否包含类似这样的内容
-----BEGIN PGP MESSAGE----- Version: GnuPG v1.2.5 (GNU/Linux) jA0EAwMCwg21r1fAW+5gyS0KR/bkeI8qPwwQo/NOaFL2LMXEYZEV9E7PBLjjGm7Y DGG4QnWD5HSNOvdaqXg= =j5Jy -----END PGP MESSAGE-----
如果包含,则表示它是 ASCII 盔甲 PGP 加密文件。
此特定文件是一个真实的加密文件,包含与上述 --print-md 示例中使用的相同值,并使用相同值的密码进行加密。
只需在未知文件上运行 GnuPG 即可生成一些有用的信息。如果它提示您输入密码,您需要获取(或猜测)用于加密该文件的密码
gpg unknown_file
如果它不是 OpenPGP 文件,您将得到类似这样的结果
gpg: no valid OpenPGP data found. gpg: processing message failed: eof
但是,如果您得到其他结果,则该文件可能已使用您没有的公钥加密。该文件也可能已损坏。一个常见的错误是通过电子邮件或 FTP 传输以 ASCII 模式发送二进制文件。
GnuPG 具有特殊的诊断选项来帮助排除这些问题。OpenPGP 消息格式在内部格式化为数据包;--list-packets 选项会转储有关这些数据包的信息
gpg --list-packets unknown_file.gpg
除了标准信息外,此选项还会打印文件加密所用公钥的完整密钥 ID(如果有)以及使用的算法。该文件可能是使用 PGP 2.x 公钥加密的,有时称为旧版密钥。PGP 2.x 早于 OpenPGP 标准,因此标准 GnuPG 无法解密它。过去几年中制作的大多数 PGP 实现通常与 OpenPGP 兼容,因此只需让发送者生成兼容的 OpenPGP 加密文件即可解决问题。
OpenPGP 还支持几种不同的加密算法。大多数实现仅包含其中一些算法。使用gpg --version查看可能缺少的内容。
有关数据包格式的详细信息(例如内部算法编号)可以在 OpenPGP 标准 RFC 2440 中找到。
表 2. 本文提到的 GnuPG 选项简短列表。
短选项 | 长选项 | 描述 |
---|---|---|
--version | 版本和算法信息 | |
--help | 帮助 | |
-a | --armor | 加密时启用 ASCII 编码 |
--enarmor | 输入二进制,输出 ASCII | |
--dearmor | 输入 ASCII,输出二进制 | |
--print-md HASH | 使用指定的 HASH 打印消息摘要 | |
-c | --symmetric | 使用密码的传统对称加密 |
-o | --output | 指定特定的输出文件,使用 - 表示 stdout |
GnuPG 主要使用长命令行选项,但某些选项也具有来自原始 PGP 的短单字母选项。例如,-v 是 --verbose,而不是 --version。
有几篇关于使用 GnuPG 更常见功能的优秀入门文章,例如 GnuPG 网站上的 Brenno de Winter 撰写的 GnuPG MiniHOWTO(请参阅“资源”)。它们详细解释了如何使用 GnuPG 更常见的公钥密码学功能。
GnuPG 邮件列表也非常有用,并且在 GnuPG 网站上完全存档。GnuPG 首席开发人员 Werner Koch 经常在邮件列表中发帖,并提供宝贵的帮助。
本文的资源: /article/8743。
Tony Stieber 是一位信息安全专业人士,专门从事 UNIX 系统、密码学和物理安全。自 1999 年以来,他一直在学习 Linux,自 1987 年以来一直在学习 UNIX,自 1980 年之前就开始学习计算机。他尚不知道未来十年会带来什么。