- 更多内容及实时更新请关注我的个人技术文档分享:www.ywenrou.cn
- 如需引用请注明出处,谢谢!
在之前的章节中,我们研究了在开放通信渠道上通信的各方的两个不同的安全概念(机密性和完整性)。在第三章中,我们关注了针对被动窃听者的机密性目标,这些被动窃听者只是简单地窃听各方的通信,然后展示了实现此目标的CPA安全加密方案。在第四章中,我们探索了针对主动攻击者的完整性目标,这些攻击者可以在通信渠道上注入消息或以其他方式篡改各方的通信,并描述了如何使用消息认证码来实现此概念。我们在5.1节中考虑缺失的部分,即在主动攻击者存在的情况下的机密性,并在那里引入了相关的CCA安全性概念。从5.2节开始,我们考虑如何构建同时实现机密性和完整性的加密方案的自然问题。
机密性是指在通信过程中,只有授权方能够访问和理解通信内容,而其他未经授权的方无法获得通信内容的信息。
完整性是指在通信过程中,通信内容没有被篡改或者损坏,且接收方能够确认通信内容确实是由发送方发出的,而不是被第三方恶意篡改过的。
到目前为止,我们只考虑了针对被动(窃听)攻击者的安全加密方案。(即使所选明文攻击允许攻击者控制加密什么内容,但在该设置中,攻击者仍然被限制在被动观察诚实方传输的密文。)在前一章中,我们讨论了防御可能干扰或修改诚实方之间通信的主动攻击者的重要性,重点是消息完整性。当涉及机密性时,主动攻击的影响会是什么呢?
在这种情况下,攻击者可以修改密文c,生成另一个密文c0并发送给接收方。接收方将解密c0以获取消息m0。如果m0≠m(且m0≠⊥),则这是完整性的违规。但是,在这里我们感兴趣的是主动攻击可能对机密性造成的潜在影响。特别是,如果攻击者从接收者的后续行为中获得了有关m0的部分信息,那么这是否会揭示有关原始消息m的信息呢?
攻击者生成密文,并迫使接收者对其进行解密的攻击类型称为选择密文攻击。从原理上讲,只要攻击者能够在发送方和接收方之间插入流量,选择密文攻击就是可能的。有许多情况会发生这种情况。(关于在公钥设置中的选择密文攻击,请参见第12.2.3节中的讨论。)例如,在第3.4.2节中的示例中,美国的密码分析员可以向日本人发送包含AF片段的加密消息;通过监视他们随后的行为(例如,部队的移动等),美国可以了解有关AF的含义的信息。
或者,可以想象一个客户端向服务器发送加密消息的情况。如果攻击者能够冒充客户端并向服务器发送看起来来自客户端的密文,服务器将解密这些密文,攻击者可能会从中获取有关结果的信息;例如,攻击者可能能够根据服务器的反应(例如,如果服务器发送错误消息),推断出某个密文解密为格式不正确的明文。在第5.1.1节中,我们详细描述了这种类型的攻击,攻击者能够利用从这些解密中泄露的信息来学习某些其他加密消息的全部内容!在实践中,此类攻击已经被用于Web服务器上,以了解加密的TLS会话的内容。
Padding-Oracle攻击是一种加密攻击类型,利用了加密算法中的漏洞,通过发送有意制造的密文并观察解密器的反应,来逐步破解密文。
我们通过展示一个现实世界的例子来说明安全防范选择性密文攻击的重要性,这种攻击可以造成灾难性后果。我们考虑一种情况,客户端使用CBC模式加密向服务器发送消息。我们假设攻击者可以冒充客户端并向服务器发送其选择的密文,服务器将解密这些密文。我们进一步假设攻击者可以确定解密后的消息是否有效(我们将在下面定义这种有效性的概念)。这样的信息通常很容易获得,例如,如果服务器接收到无法正确解密的密文,可能会要求重新传输或终止会话,任何这些事件都可以被攻击者检测到。该攻击已被证明在各种已部署的协议中有效。
在第3.6.3节中我们讨论了CBC模式加密,只考虑了消息长度是基础块密码F的块长度倍数的情况。如果消息不满足这个条件,就必须在应用CBC模式之前对其进行填充;我们称填充后的结果为编码数据。填充必须允许接收方从编码数据中明确地恢复原始消息。一种流行的填充方案由PKCS#7标准定义,其工作原理如下。假设原始消息具有整数个字节,让L表示块密码F的块长度(以字节为单位)。让b > 0表示需要附加到消息中的字节数,以使最终编码数据的总长度成为块长度的倍数。然后,我们将整数b(表示为一个字节,即两个十六进制数字)重复b次附加到消息上。也就是说,如果需要一个字节的填充,则附加1字节的字符串0x01(以十六进制写入);如果需要四个字节的填充,则附加0x04040404;以此类推。(请注意,b是介于1和L之间的整数,包括1和L。我们不能让b = 0,因为这会导致填充不明确。因此,如果原始消息长度已经是块长度的倍数,则b = L。)填充后,使用常规的CBC模式加密对编码数据进行加密。
在解密时,服务器首先像往常一样使用CBC模式解密来恢复编码数据,然后检查编码数据是否正确填充。(这很容易做到:只需读取最后一个字节的值b,然后验证结果的最后b个字节是否都具有b的值。)如果是这样,就去除填充并返回原始消息。否则,标准程序就会返回“坏填充”错误。这意味着服务器为对手提供了“填充预言机”的服务:即,对手可以向服务器发送任意密文,并根据是否返回“坏填充”错误来了解底层编码数据是否正确填充。虽然这可能看起来是无意义的信息,但我们展示了它使得对手能够完全恢复与其选择的任何密文相对应的原始消息。
下面的文字描述了对使用CBC模式加密的密文的攻击。假设攻击者观察到了一个由三个块组成的密文,其中第一个块是初始化向量(IV),第二个块是 c 1 c_1 c1,第三个块是 c 2 c_2 c2。攻击者不知道这些块对应的底层编码数据 m 1 m_1 m1 和 m 2 m_2 m2,这些数据是填充后的消息。
每个块的长度为 L L L 字节。注意到:
m 2 = F k − 1 ( c 2 ) ⊕ c 1 m_2 = F_k^{-1}(c_2) \oplus c_1 m2=Fk−1(c2)⊕c1
其中 k k k 是被诚实方使用的密钥(攻击者不知道), F k − 1 F_k^{-1} Fk−1 表示 k k k 的逆元, ⊕ \oplus ⊕ 表示异或操作。第二个块 m 2 m_2 m2 以 0 x b ⋯ 0 x b 0xb \cdots 0xb 0xb⋯0xb (共 b b b 个字节)结尾,其中 0 x b 0xb 0xb 表示某个整数 b b b 的 1 字节表示。攻击的关键在于,对密文进行某些修改后,CBC模式解密后的底层编码数据会产生可预测的变化。具体来说,攻击者可以通过修改密文的最后一个字节,得到一个新的密文 c 1 ′ c_{1}' c1′,然后解密 I V , c 1 ′ , c 2 IV, c_{1}', c_2 IV,c1′,c2,得到底层编码数据 m 1 ′ m_{1}' m1′ 和 m 2 ′ m_{2}' m2′,其中 m 2 ′ = F k − 1 ( c 2 ) ⊕ c 1 ′ m_{2}' = F_k^{-1}(c_2) \oplus c_{1}' m2′=Fk−1(c2)⊕c1′。与上面的公式相比,可以看出 m 2 ′ m_{2}' m2′ 与 m 2 m_2 m2 在最后一个字节以外是相同的,只有最后一个字节不同。攻击者还可以通过修改密文的第 i i i 个字节,得到一个新的密文 c 1 ′ c_{1}' c1′,然后解密 I V , c 1 ′ , c 2 IV, c_{1}', c_2 IV,c1′,c2,得到底层编码数据 m 1 ′ m_{1}' m1′ 和 m 2 ′ m_{2}' m2′,其中 m 2 ′ m_{2}' m2′ 在第 i i i 个字节以外与 m 2 m_2 m2 是相同的,只有第 i i i 个字节不同。更一般地,如果 c 1 ′ = c 1 ⊕ Δ c_{1}' = c_1 \oplus \Delta c1′=c1⊕Δ,其中 Δ \Delta Δ 是任意字符串,则解密 I V , c 1 ′ , c 2 IV, c_{1}', c_2 IV,c1′,c2 将产生 m 1 ′ m_{1}' m1′ 和 m 2 ′ m_{2}' m2′,其中 m 2 ′ = m 2 ⊕ Δ m_{2}' = m_2 \oplus \Delta m2′=m2⊕Δ。这意味着攻击者可以对底层编码数据的最后一个块进行控制。
因此,攻击者可以通过对密文进行修改,控制底层编码数据的最后一个块,从而破解系统的安全性。这种攻击方法被称为“填充攻击”(padding attack),是一种常见的加密攻击手段。在实际应用中,应该使用适当的加密和认证技术,以防止这种攻击。
作为热身,让我们看看攻击者如何利用此方法来了解填充长度 b b b(原始消息的长度)。回想一下,在解密时,服务器查看编码数据的最后一个字节的值 b b b,然后验证最后的 b b b 个字节是否都具有相同的值。攻击者首先修改 c 1 c_1 c1 的第一个字节,然后将结果密文 I V , c 1 ′ , c 2 IV, c_{1}', c_2 IV,c1′,c2 发送给服务器。如果解密失败(即服务器返回错误),则必须满足服务器检查 m 2 ′ m_{2}' m2′ 的所有 L L L 个字节,因此 b = L b = L b=L!否则,攻击者就会得知 b < L b < L b<L,然后可以重复这个过程,修改第二个字节,以此类推。解密失败的最左侧修改字节恰好揭示了服务器检查的最左侧字节,因此也揭示了确切的 b b b。
已知 b,攻击者可以逐个学习消息的字节。我们以消息的最后一个字节 M 为例进行说明。攻击者知道 m 2 m_2 m2 以 0 x M 0 x b ⋅ ⋅ ⋅ 0 x b 0xM0xb · · · 0xb 0xM0xb⋅⋅⋅0xb(0xb 重复 b 次)结尾,并希望学习 M。对于 0 ≤ i < 2 8 0 ≤ i < 2^8 0≤i<28(一个字节是8位)
,定义
即, ∆ i ∆_i ∆i的最后 b + 1 个字节包含整数 i(十六进制)和值 (b + 1) ⊕ b(十六进制)重复 b 次。如果攻击者向服务器提交密文 IV, c 1 c_1 c1⊕ ∆ i ∆_i ∆i, c 2 c_2 c2,则在 CBC 模式解密后,所得到的编码数据的最后 b + 1 个字节将等于 0 x ( M ⊕ i ) 0 x ( b + 1 ) ⋅ ⋅ ⋅ 0 x ( b + 1 ) 0x(M⊕i)0x(b+1)· · · 0x(b+1) 0x(M⊕i)0x(b+1)⋅⋅⋅0x(b+1)(其中 0x(b+1) 重复 b 次),除非 0 x ( M ⊕ i ) = 0 x ( b + 1 ) 0x(M ⊕ i) = 0x(b + 1) 0x(M⊕i)=0x(b+1)。攻击者尝试最多 2 8 2^8 28 个值 ∆ 0 , . . . , ∆ 2 8 − 1 ∆_0, . . . , ∆_{2^8-1} ∆0,...,∆28−1,直到某个 ∆ i ∆_i ∆i解密成功,此时它学到 M = 0 x ( b + 1 ) ⊕ 0 x i M = 0x(b + 1) ⊕ 0xi M=0x(b+1)⊕0xi。我们留给读者作为练习,将此攻击扩展到学习 m 2 m_2 m2 的下一个字节以及所有 m 1 m_1 m1 的字节。
填充攻击对CAPTCHA的影响。我们已经提到过填充攻击已经被用于加密的网络流量。这里我们给出第二个例子。
CAPTCHA是一个扭曲的图像,例如一个易于人类阅读但难以计算机处理的英文单词。CAPTCHA用于确保一个人类用户而不是一些自动化软件正在与一个网页交互。
CAPTCHA可以作为一个独立服务器上运行的单独服务来提供。为了说明这是如何工作的,我们用SW表示一个Web服务器,用SC表示一个CAPTCHA服务器,用U表示一个用户。当U加载由SW提供的网页时,会发生以下事件:SW使用最初在SW和SC之间共享的密钥k对一个随机的英文单词w进行加密,并将结果密文(以及网页)发送给用户。用户将密文转发给SC,SC解密并获得w,还会呈现w的扭曲图像(即CAPTCHA)给U。最后,U将w发送回SW进行验证。请注意,SC会解密它从U收到的任何密文,并在解密失败时发出“错误填充”错误消息,就像之前描述的那样。这为U提供了进行填充攻击的机会,从而自动解决CAPTCHA(即确定w),而无需任何人类参与,使CAPTCHA失效。
一个加密方案要安全地抵御选择密文攻击,意味着什么?通常情况下,为了定义一个适当的安全性概念,我们需要定义两件事情:攻击者的假设能力和什么构成了成功的攻击。对于后者,我们将遵循我们在几个先前的加密安全性定义中采用的方法(例如在第3.8节和第3.21节的定义中):即,我们给攻击者一个挑战密文c,该密文是通过加密两个可能的消息 m 0 , m 1 m_0,m_1 m0,m1中的一个生成的(每个消息的选择概率相等)。如果攻击者能够以比1/2显著更好的概率确定加密的是哪个消息,那么我们认为该方案已经被攻破了。
在现在的情况下,我们应该如何模拟攻击者的能力?现在,攻击者不仅应该能够获得其选择的消息的加密结果(如选择明文攻击中所示),还应该能够获得其选择的密文的解密结果(除了后面讨论的一个例外)。形式上,我们除了给攻击者访问加密预言机Enck(·)外,还给他访问解密预言机Deck(·)。我们在下面给出正式定义,并推迟进一步讨论。
对于任何私钥加密方案Π =(Gen,Enc,Dec),攻击者A和安全参数n,考虑以下实验:
定义5.1:对于所有概率多项式时间攻击者 A A A,如果存在一个可以忽略的函数 negl \text{negl} negl,那么私钥加密方案 Π \Pi Π 是在选择密文攻击下不可区分的,或者称为CCA安全性。
换句话说,如果对于所有的攻击者 A A A,其成功攻击的概率仅仅是在可以忽略的范围内优于随机猜测,那么我们认为该加密方案是CCA安全的。更正式地,对于所有的概率多项式时间攻击者 A A A,我们有:
KaTeX parse error: Can't use function '$' in math mode at position 67: …+\text{negl}(n)$̲
其中, P r i v K A , Π c c a ( n ) PrivK_{A,Π}^{cca}(n) PrivKA,Πcca(n)表示在上述CCA不可区分实验中,攻击者 A A A 成功的概率。函数 negl ( n ) \text{negl}(n) negl(n) 是一个可以忽略的函数,它表示在安全参数 n n n 趋近于无穷大时,函数值趋近于 0 0 0。如果该不等式成立,则我们认为加密方案 Π \Pi Π 在选择密文攻击下是安全的。
为了完整起见,我们指出定理 3.23的类比也适用于CCA安全性——即,如果一个加密方案在选择密文攻击下具有不可区分的加密,则它在选择密文攻击下具有不可区分的多重加密,适当地定义。
讨论.
在上述考虑的实验中,攻击者可以访问一个解密预言机,该预言机返回解密攻击者提供的密文的全部结果。一般来说,这可能比攻击者在现实世界中能够获得的信息要多得多;例如,在之前描述的填充预言机场景中,攻击者只能了解解密是否导致错误。然而,通常情况下,我们希望尽可能地使加密定义强大,以便能够广泛适用。由于我们不知道攻击者在发送的密文被接收方解密时可能了解到的信息,因此我们假设攻击者了解所有信息,以最坏情况为基础进行定义。
但还有一个注意点。在实验中,攻击者可以向解密预言机提交其选择的任何密文,但不能请求解密挑战密文本身。这个限制显然是必要的,否则没有任何加密方案能够满足定义。即使有了这个限制,定义仍然提供了有意义的安全性。特别是,需要注意的是,在填充预言机攻击的情况下,攻击者通过让接收方解密挑战密文不会获得任何信息(因为攻击者知道这不会导致错误),因此CCA安全的方案不会受到该攻击的威胁。
前面研究方案的不安全性。到目前为止,已给出的加密方案中都不是CCA安全的。我们以构造3.28为例,其中消息m的加密采用 < r , F k ( r ) ⊕ m >
考虑在CCA不可区分实验中运行的攻击者A,选择 m 0 m_0 m0和 m 1 m_1 m1都是长度为n的比特串。然后,当接收到密文c =
CCA安全性非常重要,但在这里我们引入了一个更强的安全概念。到目前为止,我们一直在考虑如何分别使用加密和消息认证码获得机密性和完整性。下面定义的认证加密的目标是同时实现这两个目标。在私钥设置中,最佳实践是默认情况下始终确保机密性和完整性。实际上,在许多需要保密的应用程序中,完整性也是必不可少的。此外,缺乏完整性有时会导致机密性的破坏,正如前一节所示。
我们像往常一样,精确定义是我们希望实现的目标。一种方法是分别定义机密性和完整性。由于我们明确关注主动攻击者,机密性的自然概念是CCA安全性。为了加密定义完整性的自然方法是通过类似于我们为MAC考虑的自适应选择消息攻击下的存在性不可伪造性的概念的类比。 (我们需要一个新的定义,因为加密方案的语法与MAC的语法不匹配。)
考虑以下为私钥加密方案 Π = ( G e n , E n c , D e c ) Π =(Gen,Enc,Dec) Π=(Gen,Enc,Dec),攻击者A和安全参数n定义的实验:
定义5.2:对于所有概率多项式时间攻击者A,存在可以忽略的函数negl,使得以下条件成立,则私钥加密方案 Π Π Π是不可伪造的:
P r [ E n c − F o r g e A , Π ( n ) = 1 ] ≤ n e g l ( n ) Pr[Enc-Forge_{A,\Pi}(n)=1] \leq negl(n) Pr[Enc−ForgeA,Π(n)=1]≤negl(n)
换句话说,攻击者即使可以访问加密算法,也无法生成解密为先前未加密过的有效明文的密文。这确保了加密方案提供机密性和完整性。需要注意的是,这个定义与CCA安全的定义不同,CCA安全允许攻击者请求解密密文。
定义5.3:如果一个私钥加密方案既是CCA安全的,又是不可伪造的,则它是一个认证加密(AE)方案。
这里还可以通过一个实验定义同时捕捉上述要求。该实验与我们之前考虑过的实验有所不同,因此我们在给出细节之前先提供一些动机。其思想是考虑两种不同的情况,并要求它们对攻击者不可区分。在第一种情况下,可以看作对应于攻击者操作的真实世界背景,攻击者具有加密和解密两个oracle。在第二种情况下,可以看作对应于“理想”情况。
定义5.4:一个私钥加密方案是一种认证加密(AE)方案,如果对于所有概率多项式时间的攻击者A,都存在一个可忽略函数negl,使得:
则私钥加密方案是一种认证加密(AE)方案。我们给出了两个认证加密的定义。幸运的是,这两个定义是等价的。
定理5.5:私钥加密方案满足定义5.3,当且仅当它满足定义5.4。
伴随数据的认证加密。通常,一个消息m需要保密性和完整性,但是与消息一起发送的各种关联数据(例如头信息)只需要完整性。虽然可以简单地将消息和关联数据连接起来(以某种允许无歧义解析的方式),然后使用AE方案对它们进行加密,但是通过仅为关联数据提供完整性保护,可以实现更好的效率。我们省略了进一步的细节,但注意,文献中将支持关联数据的AE方案称为带有关联数据的认证加密(AEAD)方案。
根据定义5.3,任何认证加密方案都是CCA安全的。然而,反之不一定成立,存在CCA安全的私钥加密方案但不是认证加密方案。关于这一点,您可以在练习5.9中证明它。
可以想象出需要CCA安全但不需要认证加密的应用程序。一个例子可能是当私钥加密用于密钥传输时。例如,当一个服务器向用户提供一个硬件令牌时,该令牌存储着一个长期密钥k。服务器可以使用私钥加密方案来向令牌发送一个短期密钥 k 0 k_0 k0,以便与令牌共享一个新的短期密钥。在这种情况下,CCA安全性是必要的,因为用户可以进行选定密文攻击以欺骗令牌。但是,由于令牌只需要验证密钥的正确性,而不需要保护消息的完整性,因此认证加密可能不是必要的。因此,这个应用程序可能需要CCA安全,但不需要认证加密。
尽管如上所述,在存在积极的对手的情况下,私钥加密的大多数应用程序确实需要完整性。幸运的是,大多数CCA安全加密方案的自然构造都满足更强的认证加密定义。换句话说,没有理由使用不是认证加密方案的CCA安全方案,因为我们没有比认证加密方案更有效的CCA安全方案构造。
然而,从概念上讲,CCA安全和认证加密的概念是不同的。关于CCA安全,我们对消息完整性本身并不感兴趣;相反,我们希望确保保密性,即使对手可以干扰从发送方到接收方的通信。相比之下,关于认证加密,我们明确关注保密性和完整性这两个目标。
很容易想到,将一个CPA安全的加密方案和一个安全的消息认证码合理地组合起来,就可以得到一个认证加密方案。在本节中,我们将展示这并非如此。这表明,即使是安全的加密工具,也可以以不安全的方式组合起来,再次强调了安全性定义和证明的重要性。但好消息是,我们将展示如何适当地组合加密和消息认证,以实现联合保密性和完整性。
在本节中,我们假设 Π E = ( E n c , D e c ) Π_E = (Enc,Dec) ΠE=(Enc,Dec) 是一个CPA安全的加密方案, Π M = ( M a c , V r f y ) Π_M = (Mac,Vrfy) ΠM=(Mac,Vrfy) 是一个强安全的消息认证码,其中两个方案的密钥生成过程仅涉及选择一个n位均匀密钥。使用 Π E Π_E ΠE和 Π M Π_M ΠM的独立密钥 k E k_E kE和 k M k_M kM,有三种自然的组合加密和消息认证的方法:
Encrypt-and-authenticate:
在这种方法中,加密和消息认证是独立并行计算的。也就是说,给定一个消息 m m m,发送方传输密文 < c , t >
c c c是对明文 m m m使用加密算法得到的密文;
t t t是对明文 m m m使用消息认证算法得到的消息认证码。
接收者解密密文 c 以恢复消息 m;假设没有发生错误,它接着验证 消息认证码 t。如果 V r f y k M ( m , t ) = 1 Vrfy_{kM}(m, t) = 1 VrfykM(m,t)=1,则接收者输出消息 m;否则,它输出一个错误。
其中 E n c k E Enc_{kE} EnckE表示使用密钥 k E k_E kE对明文进行加密, M a c k M Mac_{kM} MackM表示使用密钥 k M k_M kM对明文进行消息认证, V r f y k M Vrfy_{kM} VrfykM表示使用密钥 k M kM kM验证消息认证码的正确性。
Authenticate-then-encrypt:
在这种方法中,首先计算出一个消息认证码 t t t,然后将消息和消息认证码一起加密。也就是说,给定一个消息 m m m,发送方传输密文 c c c,其中:
t t t是对明文 m m m使用消息认证算法得到的消息认证码;
c c c是对拼接的数据 m ∣ ∣ t m||t m∣∣t使用加密算法得到的密文。
接收方首先解密 c c c以获得 m ∣ ∣ t m||t m∣∣t;假设没有发生错误,它接着验证 消息认证码t。与之前一样,如果 V r f y k M ( m , t ) = 1 Vrfy_{kM}(m, t) = 1 VrfykM(m,t)=1,则接收者输出消息 m m m;否则,它输出一个错误。
我们分析了上述每种方法,当它们使用“通用”的安全组件时进行实例化,即使用任意CPA安全的加密方案和任意强安全的消息认证码。我们寻找一种方法,无论使用何种(安全的)组件,都能提供联合保密性和完整性,因此拒绝任何这种情况下无法实现的方法,这样可以减少实现缺陷的可能性。具体而言,一种方法可能通过调用“加密子例程”和“消息认证子例程”来实现,这些子例程的实现可能在以后的某个时间点进行更改(这通常发生在加密库更新或标准修改时)。因此,一个方法的安全性取决于其基础组件的实现细节,而不是它们提供的安全性,因此是危险的。
我们强调,如果一个方法被拒绝,这并不意味着它对所有可能的组件实例化都是不安全的;然而,这意味着任何方法的实例化必须在使用之前经过仔细分析和证明其安全性。
本章最后,我们简要介绍了三种实际中使用的AE方案,每种方案都受到之前讨论过的一种方法的启发。和往常一样,我们的目的不是提供这些方案的详细描述,而只是提供对构造的高层次理解。
GCM(Galois/Counter Mode)。GCM可以看作是遵循加密-认证范式的方案,其中CTR模式(参见第3.6.3节)作为底层加密方案,GMAC(参见第4.5.2节)作为底层消息认证码。与前一节中描述的通用组合的主要区别是:(1)用于加密和认证的密钥不是独立的,(2)相同的IV既用于CTR模式加密,也用作GMAC的随机数。这两个变化都可以在GCM的特定实现中被证明是安全的。
使用GCM时需要注意的一个重要属性是,如果IV重复了,则不仅使用相同IV加密的两个消息的保密性会失败,而且方案的完整性可能会完全破坏。这是由GMAC的一个特性引起的,该特性在练习4.21中进行了讨论。因此,使用GCM时必须非常小心地确保IV不重复。
当使用AES块密码(参见第7.2.5节)实例化GCM时,由于针对AES和GMAC中使用的域操作的专用硬件指令,它在大多数现代处理器上非常快速。该方案还可以高度并行化。
CCM (Counter with CBC-MAC)。CCM遵循认证-加密方法,其中CTR模式是底层加密方案,CBC-MAC(参见第4.4.1节)是底层消息认证码。此外,相同的密钥k用于两者。虽然如前一节所述,认证-加密方法通常不安全,并且在加密和认证使用的密钥不独立时可能会出现问题,但CCM本身可以被证明是安全的。
因为CCM只依赖于使用单个密钥的块密码,所以它容易实现。然而,CCM相对较慢(它需要每个明文块进行两个块密码评估),并且不能完全并行化。此外,它不能在线上使用,因为它要求在加密开始前知道消息长度(这是因为在计算CBC-MAC之前,长度被预先添加到消息中,如第4.4.1节所述)。
ChaCha20-Poly1305。这种方案依赖于加密-认证方法,在此方法中,底层加密使用不同步模式下的流密码ChaCha20(参见第7.1.5节),使用Poly1305(参见第4.5.2节)作为MAC,并使用ChaCha20来实现伪随机函数。这种方案在软件中非常快速,并且正在成为平台上的首选方法,其中GCM使用的专用硬件指令不可用。
我们简要描述了认证加密方案在两个希望在通信会话期间“安全”地通信的双方之间的应用——即,希望具有联合保密性和完整性。在此部分,我们故意不正式;一个正式的定义相当复杂,而且这个主题在网络安全领域中的重要性更大于密码学领域。
设 Π = ( E n c , D e c ) Π = (Enc,Dec) Π=(Enc,Dec)为认证加密方案。考虑两个共享密钥k的A和B希望在会话期间使用此密钥来保护他们的通信。这里明显要做的是使用Π:每当,比如,A想要向B传输消息m时,她计算 c ← E n c k ( m ) c ← Enc_k(m) c←Enck(m)并将c发送给B;反过来,B解密c以恢复结果(如果解密返回 ⊥,则忽略结果)。同样,当B想向A发送消息时,也遵循同样的过程。然而,这种简单的方法容易受到各种潜在攻击的影响:
重新排序攻击:攻击者可以交换消息的顺序。例如,如果A传输 c 1 c_1 c1( m 1 m_1 m1的加密)然后传输 c 2 c_2 c2( m 2 m_2 m2的加密),那么具有一定网络控制权的攻击者可以在 c 1 c_1 c1之前传递 c 2 c_2 c2,从而导致B按错误的顺序输出消息。
重放攻击:攻击者可以重放一个(有效的)先前由其中一方发送的密文c。这将导致一方输出消息两次,尽管另一方只发送了一次。
丢失消息攻击:攻击者可能会丢弃A和B之间发送的某些消息。虽然没有什么可以阻止攻击者这样做,但我们至少可以希望这种行为会被检测到。
反射攻击:攻击者可以将从A发送到B的密文c发送回A。这将导致A输出消息m,尽管B从未发送过这样的消息。
上述攻击列表并不详尽,只是一些实现安全通信所涉及的挑战的例子。
可以使用计数器来处理前三个攻击,使用方向位来防止第四个攻击。
计数器可以用来标识消息的顺序,并确保每个消息只被处理一次。每当一方发送一条新消息时,计数器就会增加一个值。接收方会记录每个接收到的消息的计数器值,并在接收到新消息时检查其计数器值是否比之前接收到的消息的计数器值更高。如果新消息的计数器值小于或等于之前接收到的消息的计数器值,则接收方会拒绝该消息,并将其视为重复的消息或已过期的消息。
方向位可以用来标识消息是从A发送到B还是从B发送到A。每当一方发送一条新消息时,它会指定一个方向位,用于指示消息的方向。接收方会检查方向位以确保消息来自正确的发送方,并拒绝任何不符合预期方向的消息。