安全通信正迅速成为当今网络的常态。2018 年 7 月,Google Chrome 计划 开始对所有 通过 HTTP(而不是 HTTPS)传输的网站显示“不安全”通知。Mozilla 也有类似的 计划。虽然密码学越来越普遍,但它并没有变得更容易理解。Let's Encrypt 设计并构建了一个很棒的解决方案,可以提供并定期续订免费的安全证书,但是如果您不理解其基本概念和陷阱,那么您只是一个大型货物崇拜程序员群体中的一员。
安全通信的属性
密码学直观的目的是保密性:一条消息可以在不被窥探的情况下传输。为了保密,我们加密一条消息:给定一条消息,我们将其与密钥配对,并生成一个毫无意义的乱码,只有通过使用相同的密钥反转该过程才能再次变得有用(从而解密它)。假设我们有两个朋友 Alice 和 Bob,以及他们爱管闲事的邻居 Eve。 Alice 可以加密一条消息,例如“Eve 很烦人”,然后将其发送给 Bob,而无需担心 Eve 窥探她。
对于真正安全的通信,我们需要的不只是保密性。假设 Eve 收集了 Alice 和 Bob 的足够多的消息,以确定单词“Eve”被加密为“Xyzzy”。此外,Eve 知道 Alice 和 Bob 正在计划一个聚会,而 Alice 将向 Bob 发送客人名单。如果 Eve 截获该消息并将“Xyzzy”添加到列表的末尾,她就成功破坏了聚会。因此,Alice 和 Bob 需要他们的通信提供完整性:消息应该不受篡改。
但是我们还有另一个问题。假设 Eve 看到 Bob 打开一个标记为“来自 Alice”的信封,里面有一条来自 Alice 的消息,内容为“再买一加仑冰淇淋”。 Eve 看到 Bob 出去并带着冰淇淋回来,因此她大致了解了消息的内容,即使她不知道确切的措辞。 Bob 扔掉了消息,Eve 找回了它,然后在接下来的每个星期每天都将一个标记为“来自 Alice”的信封副本放入 Bob 的邮箱。现在聚会上有太多的冰淇淋,当 Bob 在晚上结束时将其送出时,Eve 就带着免费的冰淇淋回家了。额外的消息是保密的,它们的完整性也完好无损,但 Bob 被误导了发送者的真实身份。身份验证是知道与您通信的人实际上是他们声称的那个人。
信息安全具有其他属性,但是保密性、完整性和身份验证是您必须知道的三个特征。
加密和密码
加密的组成部分是什么?我们需要一条消息,我们称之为明文。我们可能需要对消息进行一些初始格式化,以使其适合加密过程(例如,如果使用分组密码,则将其填充到一定长度)。然后我们采用一个称为密钥的秘密位序列。然后,密码采用密钥并将明文转换为密文。密文应看起来像随机噪声,只有通过使用相同的密码和相同的密钥(或者正如我们稍后将在非对称密码中看到的那样,使用数学相关的密钥)才能恢复明文。
密码使用密钥的位转换明文的位。由于我们希望能够解密密文,因此我们的密码也需要是可逆的。我们可以使用 XOR 作为一个简单的例子。它是可逆的,并且是自身的逆运算 (P ^ K = C; C ^ K = P),因此它可以同时加密明文和解密密文。 XOR 的一个简单用法可以用于一次性密码本中的加密,但通常不实用。但是,可以将 XOR 与一个从单个密钥生成任意随机数据流的函数组合在一起。诸如 AES 和 Chacha20 之类的现代密码正是这样做的。
我们将任何使用相同密钥来加密和解密的密码称为对称密码。对称密码分为流密码和分组密码。流密码一次一位或一个字节地运行消息。例如,我们的 XOR 密码就是一种流密码。如果明文的长度未知(例如,来自管道或套接字的数据),则流密码非常有用。 RC4 是最著名的流密码,但它容易受到几种不同攻击的影响,并且 TLS 协议(“HTTPS”中的“S”)的最新版本(1.3)甚至不支持它。 人们正在努力创建新的流密码,其中一些候选密码(例如 ChaCha20)已经在 TLS 中得到支持。
分组密码采用固定大小的块并使用固定大小的密钥对其进行加密。当前分组密码领域中的王者是高级加密标准 (AES),它的块大小为 128 位。这不是很多数据,因此分组密码具有模式,该模式描述了如何将密码的分组操作应用于任意大小的消息。最简单的模式是电子密码本 (ECB),它接收消息,将其拆分为块(必要时填充消息的最后一个块),然后使用密钥独立地加密每个块。

您可能会在这里发现一个问题:如果相同的块在消息中出现多次(例如,Web 流量中的短语“GET / HTTP/1.1”),并且我们使用相同的密钥对其进行加密,我们将得到相同的结果。加密通信中出现的模式使其容易受到攻击。
因此,有更高级的模式,例如密码块链接 (CBC),其中每个块加密的结果与下一个块的明文进行异或运算。第一个块的明文与随机数的初始化向量进行异或运算。还有许多其他模式,每种模式在安全性和速度方面都有不同的优点和缺点。甚至有一些模式,例如计数器 (CTR),可以将分组密码转换为流密码。

与对称密码相反,存在非对称密码(也称为公钥密码)。这些密码使用两个密钥:公钥和私钥。密钥在数学上相关,但仍然不同。用公钥加密的任何内容只能用私钥解密,而用私钥加密的数据可以用公钥解密。公钥被广泛分发,而私钥则保密。如果您想与某人通信,可以使用他们的公钥来加密您的消息,并且只有他们的私钥才能解密它。 RSA 是当前非对称密码的重量级冠军。
非对称密码的主要缺点是它们在计算上非常昂贵。我们可以通过对称密码进行身份验证来加快速度吗?如果您只与另一个人共享密钥,则可以。但这很快就会崩溃。假设一群人想使用对称密码相互通信。组成员可以为每个成员的唯一配对建立密钥,并根据收件人加密消息,但是一个由 20 个人组成的组总共有 190 对成员,并且每个人都需要管理和保护 19 个密钥。通过使用非对称密码,每个人只需要保护自己的私钥并可以访问公钥列表。
非对称密码也限制了它们可以加密的 数据量。与分组密码一样,您必须将较长的消息分成几段。因此,在实践中,非对称密码通常用于建立保密的、经过身份验证的通道,然后用于交换对称密码的共享密钥。对称密码用于后续通信,因为它速度更快。 TLS 可以以这种方式运行。
基础
安全通信的核心是随机数。随机数用于生成密钥,并为原本确定性的过程提供不可预测性。如果我们使用的密钥是可预测的,那么我们从一开始就容易受到攻击。在旨在以一致方式运行的计算机上,随机数很难生成。计算机可以从鼠标移动或键盘时序等事物中收集随机数据。但是,收集这种随机性(称为熵)需要大量时间,并且需要额外的处理来确保均匀分布。它甚至可能涉及使用专用硬件(例如一整面熔岩灯墙)。通常,一旦我们有了真正的随机值,我们就会将其用作种子放入密码学安全的伪随机数生成器。从相同的种子开始总是会导致相同的数字流,但重要的是,从种子派生的数字流不表现出任何模式。在 Linux 内核中,/dev/random 和 /dev/urandom以这种方式运行:它们从多个来源收集熵,对其进行处理以消除偏差,创建一个种子,然后可以提供用于生成例如 RSA 密钥的随机数。
其他密码学构建块
我们已经介绍了机密性,但我还没有提到完整性或身份验证。为此,我们需要工具箱中的一些新工具。
第一个是密码学哈希函数。密码学哈希函数旨在获取任意大小的输入并产生固定大小的输出(通常称为摘要)。如果我们能找到任何两条消息产生相同的摘要,那就是冲突,并且使哈希函数不适合密码学。请注意对“找到”的强调;如果我们有一个无限的消息世界和一个固定大小的输出,那么必然会发生冲突,但是如果我们可以在不投入大量计算资源的情况下找到任何两条冲突的消息,那就是一个问题。更糟糕的是,如果我们能够获取一条特定的消息,然后找到另一条导致冲突的消息。
同样,哈希函数应该是单向的:给定一个摘要,应该在计算上不可行地确定消息是什么。分别地,这些要求被称为抗碰撞性、抗第二原像性和抗原像性。如果我们满足这些要求,我们的摘要就充当消息的一种指纹。没有人(理论上)拥有相同的指纹,并且你不能获取指纹并将其变回一个人。
如果我们发送一条消息和一个摘要,接收者可以使用相同的哈希函数来生成独立的摘要。如果两个摘要匹配,他们就知道消息没有被更改。SHA-256是目前最流行的密码学哈希函数,因为SHA-1开始显示出其局限性。
哈希听起来不错,但如果有人可以篡改你的消息,然后篡改摘要,那么发送带有摘要的消息有什么好处?我们需要将哈希与我们拥有的密码混合在一起。对于对称密码,我们有消息认证码 (MAC)。 MAC 有不同的形式,但 HMAC 基于哈希。HMAC采用密钥 K 和消息 M,并使用哈希函数 H 将它们混合在一起,公式为 H(K + H(K + M)),其中“+”是连接。 为什么是这个特定的公式? 这超出了本文的范围,但这与保护 HMAC 本身的完整性有关。 MAC 与加密消息一起发送。 Eve 可以盲目地操纵消息,但只要 Bob 独立计算 MAC 并将其与他收到的 MAC 进行比较,他就会意识到消息已被篡改。
对于非对称密码,我们有数字签名。 在 RSA 中,使用公钥加密使只有私钥可以解密某些东西,但反过来也是如此,并且可以创建一种签名类型。 如果只有我有私钥并加密文档,那么只有我的公钥会解密该文档,其他人可以隐式地信任是我写的:身份验证。 事实上,我们甚至不需要加密整个文档。 如果我们创建文档的摘要,我们可以只加密指纹。 签署摘要而不是整个文档速度更快,并解决了一些关于可以使用非对称加密加密的消息大小的问题。 接收者解密摘要,独立计算消息的摘要,然后比较两者以确保完整性。 其他非对称密码的数字签名方法各不相同,但使用公钥验证签名的概念仍然存在。
整合在一起
现在我们有了所有主要部分,我们可以实现一个具有我们正在寻找的所有三个属性的系统。 Alice 选择一个秘密对称密钥,并使用 Bob 的公钥对其进行加密。 然后,她对生成的密文进行哈希处理,并使用她的私钥对摘要进行签名。 Bob 收到密文和签名,计算密文的摘要,并将其与使用 Alice 的公钥验证的签名中的摘要进行比较。 如果两个摘要相同,他知道对称密钥具有完整性并且经过身份验证。 他使用他的私钥解密密文,并使用 Alice 发送给他的对称密钥与她进行机密通信,并对每条消息使用 HMAC 以确保完整性。 这里没有针对消息被重放的保护(如 Eve 造成的冰淇淋灾难中所见)。 为了处理这个问题,我们需要某种“握手”来建立一个随机的、短期的会话标识符。
密码学世界广阔而复杂,但我希望本文能为您提供其核心目标和组件的基本心理模型。 凭借对概念的扎实基础,您将能够继续学习更多内容。
感谢 Hubert Kario、Florian Weimer 和 Mike Bursell 对本文的帮助。
1 条评论