OpenSSL 技巧

作者:Anthony J. Stieber

OpenSSL 是一个强大的安全套接层密码学库。Apache 使用它进行 HTTPS 加密,而 OpenSSH 使用它进行 SSH 加密。但是,您不必将其用作库。它也是一个多用途、跨平台的密码学工具。

以下是关于 OpenSSL 的一些背景知识。在 OpenSSL 之前,有一个 ssleay,它是 Eric A. Young 编写的 SSL 实现。它经过不断改进,最终成为 OpenSSL,类似于 NCSA HTTPd 如何成为 Apache Web 服务器。如今,OpenSSL 支持数十种密码学算法和协议,以及数百个选项。

OpenSSL 具有许多功能。除了 SSL 客户端和服务器功能外,OpenSSL 还具有:

  • 美国联邦政府 NIST FIPS 140-2 1 级验证。

  • TLS,下一代 SSL。

  • X.509 密钥和证书生成。

  • X.509 证书授权中心。

  • S/MIME 加密。

  • 文件加密和哈希。

  • UNIX 密码哈希。

  • 九种不同的商业密码学硬件设备。

  • 密码学性能测试。

  • 三十六个命令。

  • 六种消息摘要算法。

  • 九种密码算法,带有四种块模式(如果适用)。

  • 多种密码学协议。

尽管 OpenSSL 很复杂,但许多复杂性是可以避免的。本文的其余部分侧重于易于使用的功能,并且只需几行 shell 代码即可完成。

本文使用与我之前的 GnuPG 文章(“GnuPG Hacks”,Linux Journal,2006 年 3 月,第 52 页)相同的章节标题,以便更轻松地比较 OpenSSL 和 GnuPG。

入门指南

首先,让我们确认 OpenSSL 已安装并在您的路径中。许多 Linux 发行版,甚至一些小型发行版,都包含 OpenSSL。通常,OpenSSL 位于 /usr/bin/ 中,就像大多数捆绑软件包一样。

在所有示例中,shell 提示符都设置为 $。

首先,输入

$ openssl version

请注意,version 选项没有前导破折号。

您应该得到类似这样的结果

OpenSSL 0.9.7d 17 Mar 2004

确切的版本号、日期和其他详细信息可能会有所不同。在撰写本文时,当前版本是 OpenSSL 0.9.8a。我们使用的示例应该适用于大多数版本的 OpenSSL。

如果您输入了openssl没有命令行选项,您将得到这个

OpenSSL>

如果发生这种情况,只需输入quit或按 Ctrl-C 安全退出。这只是 OpenSSL 的内部命令行提示符。它没有命令行编辑功能,也没有明确的帮助功能。但是,如果您输入它不认识的命令,它将键入命令列表。现在最好避免使用它。

二进制文件保护

二进制文件通常使用 MIME 在电子邮件中发送。但是,如果您的电子邮件软件不支持 MIME,就像大多数命令行电子邮件一样,您会被 uuencode 困住,或者您可以使用 OpenSSL 的 base64 编码。Base64 与更复杂的 MIME 协议使用的编码相同,但它不是直接与 MIME 兼容的。

要将文件包装在 base64 文本编码中,请输入

$ openssl base64 < filename.bin > filename.txt

要解包 base64 编码的文件,请输入

$ openssl base64 -d < filename.txt > filename.bin

请注意,OpenSSL 不关心文件名扩展名。

与 GnuPG 或 MIME 不同,OpenSSL 还可以编码短字符串,如下所示:

$ echo "The Linux Journal" | openssl base64
VGhlIExpbnV4IEpvdXJuYWwK

解码类似:

$ echo "VGhlIExpbnV4IEpvdXJuYWwK" | openssl base64 -d
The Linux Journal

请注意 -d 选项,它指定解码。

更好的校验和

sum 和 cksum 是传统的 UNIX 校验和程序。它们工作正常,只要您不需要跨平台兼容性或安全性,并且您不介意偶尔两个完全不同的文件会具有相同的校验和值。

尽管 Linux 系统通常安装了 md5sum,但 MD5 算法存在相对较新的漏洞,不应再使用。

如果已安装,则应使用更安全的 sha1sum。但是,有几个不同的程序使用这个名称。某些版本一次只能哈希一个文件,某些版本无法处理 stdin 或存在其他缺陷。如果您遇到任何这些问题,或者只是想要一致、已知、良好的跨平台软件,请考虑使用 OpenSSL。

OpenSSL 哈希输出格式与 GnuPG 略有不同,但在数值上是相同的。OpenSSL 格式始终标识使用的算法,并输出一个没有空格的小写十六进制字符串。有些人觉得这种格式更容易使用。

以下是一些示例:

$ openssl sha1 filename
SHA1(filename)= e83a42b9bc8431a6645099be50b6341a35d3dceb

$ openssl md5 filename
MD5(filename)= 26e9855f8ad6a5906fea121283c729c4

与我之前的“GnuPG Hacks”文章一样,以上示例使用包含字符串的文件:“The Linux Journal”。请注意,字符串中没有句点。

如果您在复制这些结果时遇到问题,这是文件的 ASCII 注释十六进制表示形式。请注意 vi 自动添加的行尾换行符

T  h  e     L  i  n  u  x     J  o  u  r  n  a  l  \n
54 68 65 20 4c 69 6e 75 78 20 4a 6f 75 72 6e 61 6c 0a

与 GnuPG 不同,OpenSSL 没有 SHA-512,但 OpenSSL 确实有 MD2、MD4 和 MDC2。这些是较旧的算法,提供用于向后兼容。与 MD5 一样,它们不应再使用。

快速简洁的加密

尽管不是 OpenSSL 的强项,但它也可以加密文件。OpenSSL 的灵活性使其比 GnuPG 稍微复杂一些。

OpenSSL 的默认设置很少,因此必须使用更多选项。还有许多算法可供选择。某些算法,如 DES 和 RC4-40,仅为向后兼容而保留,不应再使用。您应使用的强大算法包括 bf(即 Blowfish 算法)和 -aes-128-cbc(即美国 NIST 高级加密标准 (AES),具有 128 位密钥,在密码块链接 (CBC) 模式下运行)。

这是一个示例:

$ openssl enc -aes-128-cbc < filename > filename.aes-128-cbc
enter aes-128-cbc encryption password:
Verifying - enter aes-128-cbc encryption password:

与 GnuPG 一样,OpenSSL 会要求输入两次密码,密码不会回显到屏幕上。

解密也稍微复杂一些:

$ openssl enc -d -aes-128-cbc -in filename.aes-128-cbc > filename
enter aes-128-cbc decryption password:

请注意此示例中的 -d,它指定解密。

与 GnuPG 不同,OpenSSL 不会自动检测文件类型,甚至不检测用于加密文件的算法、密钥长度和模式。您需要自己跟踪这些信息。在我的示例中,我已将该信息放在文件名扩展名中。OpenSSL 不会为您管理文件和文件扩展名,您必须指定要将传出数据写入的位置。

如果您未指定正确的算法,OpenSSL 可能会输出乱码或抱怨错误的魔数。无论哪种方式,如果没有正确的选项,您的数据都将无法正确解密。公平地说,这根本不是 OpenSSL 设计的目的,但它确实有效。

密码短语

在我们进一步讨论之前,我们应该讨论密码短语的重要性。在大多数密码系统中,密码短语是保护其他秘密的秘密。它通常是最薄弱的环节。因此,创建强密码短语很重要,但也很困难,除非您拥有合适的工具。使用 OpenSSL,您可以快速创建强密码短语。

密码短语的简单指南是,密码短语越长越好,八个字符是不够长的(表 1)。目标是创建一个您可以记住的秘密,但其他人不知道、猜不到或最终不会偶然发现的秘密。

表 1. 密码和密码短语强度与估计破解时间比较。注意:破解时间非常粗略。您的破解情况可能会有所不同。

类型字节字符每字符位数总位数破解时间
Base64 [A-Za-z0-9+/=]68648几分钟到几小时
Base64 [A-Za-z0-9+/=]912672
Base64 [A-Za-z0-9+/=]1216696数十年
Base64 [A-Za-z0-9+/=]15206120无法破解?
Diceware 密码短语 8 个单词每个单词 12.9 位120无法破解?
生成密码短语

OpenSSL 可以创建非常强大的随机密码短语,如下所示:

$ openssl rand 15 -base64
wGcwstkb8Er0g6w1+Dm+

如果您运行此示例,您的输出将与示例不同,因为密码短语是随机生成的。

第一个参数 15 是要生成的二进制字节数,第二个参数 -base64 指定应将这些二进制字节编码为 base64 字符。对于 15 个字节,输出始终为 20 个字符,外加一个换行符。

base64 字符集仅包含大写和小写字母 A–Z、数字 1–9 和三个标点符号:加号、斜杠和等号。这有意限制了字符集,但字符集中的更多复杂性不一定更好。仅添加一个额外的字符就可以弥补安全性的差异。例如,一个八个字符的完全可打印的 ASCII 密码与一个九个字符的 base64 密码强度大致相同。

虽然不如使用OpenSSL rand快,但 Diceware 密码短语生成器可以生成强大且通常易于记忆的密码短语。我强烈推荐它。

加密密码

这是 GnuPG 无法做到的。OpenSSL 有一个内置命令,用于创建加密的 Linux 密码,与 /bin/passwd 创建的密码完全一样。

跳过此段落以避免学究式的密码学解释。尽管通常称为加密,但 Linux 密码实际上是使用 MD5 或旧的 UNIX 密码哈希(基于 DES 加密算法)进行哈希处理的。这使得 Linux 不知道您的密码,即使它知道您何时提供正确的密码。当您设置密码时,Linux 会对您的密码进行哈希处理并将其存储在 /etc/shadow 中。当您登录时,Linux 会获取您提供的密码并再次对其进行哈希处理,然后将该哈希值与存储在 /etc/shadow 中您的帐户的哈希值进行比较。如果它们匹配,则您提供了正确的密码并且可以登录。如果它们不匹配,则您不知道您的密码,并且由于仅存储了哈希值,因此计算机也不知道您的密码。

以下是制作您自己的密码哈希有用的原因。假设您在另一台计算机上需要一个新密码。也许这是一个新帐户,或者您忘记了旧密码并要求系统管理员为您重置密码。如果您可以亲自与系统管理员交谈,这效果很好,但如果系统管理员在其他地方怎么办?也许您甚至从未见过您的系统管理员。您如何传达您的新密码?电子邮件一点也不安全,电话也好不到哪里去。邮寄需要几天时间(并且存在其他安全问题)。传真机、短信和大多数寻呼机也不安全。

情况变得更糟。也许您甚至不信任该系统管理员。当然,系统管理员通常具有 root 权限,但其他人知道您的密码甚至会绕过 root 责任。也许您想在其他计算机上使用相同的密码,并且您也不信任这些系统管理员。

因此,请改为执行此操作:

$ openssl passwd -1
Password:
Verifying - Password:
$1$zmUy5lry$aG45DkcaJwM/GNlpBLTDy0

输入您的新密码两次;密码不会回显。如果您有多个帐户,请多次运行以上示例。输出是您的密码的密码学哈希值。哈希值是随机加盐的,因此每次运行时,输出都会不同,即使密码相同。

在我的示例中,密码哈希为:

$1$zmUy5lry$aG45DkcaJwM/GNlpBLTDy0

您的密码哈希可能会完全不同,除了初始的 $1$。

现在可以通过电子邮件、传真、短信甚至通过电话将此密码哈希发送给系统管理员,以将其设置为您的密码哈希。

系统管理员收到您的密码哈希后,可以手动或使用 chpasswd 将其输入到 /etc/shadow 中。后者需要一个临时新文件,称之为 newpassword,其中包含您的登录 ID 和密码哈希,如下所示:

LoginidHere:$1$ywrU2ttf$yjm9OXTIBnoKJLQK2Fw5c/

该文件也可以包含其他帐户的多行。

然后,系统管理员以 root 身份运行此命令:

chpasswd --encrypted < newpassword

现在,新密码已设置。最好在登录后更改您的密码,除非您使用非常强的密码短语。这是因为密码哈希一旦暴露,就会受到离线暴力破解攻击,除非密码非常长。

这种重置密码的方法可能非常安全。例如,使用此技术,有人可以获取上面发布的密码哈希,创建一个帐户,然后告诉该人登录 ID 和主机名,以及使用了上面的密码哈希。只有最初创建密码哈希的人才知道密码,即使密码哈希已在杂志上发布。

顺便说一句,该哈希的密码是 28 个完全随机的 base64 字符长,因此应该极难破解。但是请不要使用该哈希创建任何帐户,因为密码也已发布,它是:

HXzNnCTo8k44k8v7iz4ZkR/QWkM2

该密码和哈希是这样创建的:

$ openssl rand 21 -base64
HXzNnCTo8k44k8v7iz4ZkR/QWkM2
$ openssl passwd -1 HXzNnCTo8k44k8v7iz4ZkR/QWkM2

这些示例使用现在 Linux 系统上常见的 MD5 密码哈希。如果您需要使用旧的 UNIX 密码哈希,只需省略 -1 即可。例如:

$ openssl passwd
Password:
Verifying - Password:
xcx7DofWC0LpQ

最后一个密码哈希示例的密码是:TheLinux.

密码学基准测试

OpenSSL 支持的多种算法使其非常适合密码学基准测试。这对于在使用一致的代码库比较不同密码学算法和不同硬件架构的相对性能非常有用。并且,它具有内置的基准测试命令。

这个openssl speed命令默认情况下会运行每个受支持模式和选项中的每个算法,并使用几种不同大小的数据。不同的大小很重要,因为算法启动开销。

完整的speed运行大约需要六分钟,与硬件性能无关,并生成 124 行性能数据和 29 行摘要。

但是,请注意,密码学算法性能在很大程度上取决于具体的实现。为了获得更高的性能,OpenSSL 针对几种算法具有 x86 汇编代码。其他架构(如 ia64、SPARC 和 x86-64)的汇编代码要少得多,而大多数其他架构则没有。汇编代码位于以下 OpenSSL 源代码目录中:crypto/*/asm。表 2 和表 3 显示了三个不同系统的速度报告摘录。

表 2. 哈希和分组密码性能(数字以千字节/秒为单位,使用 1,024 字节块。)

 AMD K6-2 300MHz,Linux 2.6.12,OpenSSL 0.9.7gAMD Athlon 1.333GHz,Linux 2.4.27,OpenSSL 0.9.7dPowerMac G5 1.6GHz,Darwin 内核版本 8.0.0,OpenSSL 0.9.7b
md526,733.93k169,207.13k76,921.71k
sha112,665.41k113,973.25k76,187.82k
blowfish cbc9,663.40k56,940.54k44,433.14k
aes-128 cbc5,134.78k31,355.90k54,987.78k

表 3. 公钥密码学性能

 签名/秒验证/秒 
rsa 1024 位30.8563.1AMD K6-2 300MHz,Linux 2.6.12,OpenSSL 0.9.7g
dsa 1024 位61.650.7AMD K6-2 300MHz,Linux 2.6.12,OpenSSL 0.9.7g
rsa 1024 位239.94,514.6AMD Athlon 1.333 GHz,Linux 2.4.27,OpenSSL 0.9.7d
dsa 1024 位498.2410.6AMD Athlon 1.333 GHz,Linux 2.4.27,OpenSSL 0.9.7d
rsa 1024 位148.82,739.1PowerMac G5 1.6 GHz,Darwin 内核版本 8.0.0,OpenSSL 0.9.7b
dsa 1024 位289.5234.6PowerMac G5 1.6 GHz,Darwin 内核版本 8.0.0,OpenSSL 0.9.7b
了解更多

这只是 OpenSSL 在命令行中提供的功能的一个示例。

在 OpenSSL 网站的“文档和相关”部分下提供了一些文档。在“支持”部分下还有几个邮件列表可用。

OpenSSL 是用 C/C++ 编写的,但它已适应其他编程语言,包括 Ruby。此外,2006 年 3 月的 FIPS 140-2 1 级验证使 OpenSSL 成为企业和政府密码学市场的新竞争者。

本文的资源: /article/9020

Anthony J. Stieber 是一位信息安全专业技术人员,他痴迷于 UNIX 系统、密码学、物理安全以及他不能告诉您的事情。他目前在美国明尼苏达州明尼阿波利斯市解冻中。这是他发表的第二篇文章。

加载 Disqus 评论