Active attack on CPA-secure encryption
修改IV域的攻击例子
在这个攻击者的例子中,他们可以篡改通信,因此完全破坏了CPA安全加密的安全性。这告诉我们,实际上那种方法提供的完整性和私密性也会被破坏,换句话说,如果我们要安全地对抗主动型攻击者,完整性和私密性,两者都必须保证。
使用一个高度简化的 TCP/IP 版本,这样我们可以关注于攻击,不拘泥于细节。我们有两个机器互相通信,一用户坐在一台机器上,另一台机器是个服务器,现在,服务器上有 TCP/IP 协议栈在接收数据包,然后,根据这些数据包的目标地址域,服务器把数据包转发到合适的位置。比如,这里我们有两个进程在监听这些数据包,一个在网页服务器这里,另一个在用户 Bob 这里,网页服务器监听 80 端口,用户 Bob 监听 25 端口。现在,当一个数据包到来时,TCP/IP 协议栈查看目标端口,在这个情况下,端口号是 80 ,因此,协议栈把数据包转发到网页服务器,如果目标端口是 25 ,TCP/IP 协议栈会把数据包转发给 Bob 。
现在,一个很有名的安全协议叫 IPsec ,加密了发送方和接收方之间的 IP 数据包,在这里,发送方和接收方共享一个密钥,当发送方发送 IP 数据包时,使用密钥 k 来加密这些 IP 包。现在,一个数据包到达了服务器,TCP/IP 栈会解密这个数据包,然后看目标端口,把数据包发送到合适的位置去解密,注意,这里的数据 data 是被加密的,这种情况下,因为目标端口是 80,会把数据发给网页服务器 ;如果目标端口正好是 25 ,TCP/IP 栈会解密这个包看目标端口,然后把明文数据 stuff 发给相应进程。
没有完整性的话,这里我们不能获得任何的私密性。为什么呢?想象一下攻击者截获了一个特定的给网页服务器的数据包,换句话说,这是个加密的目标端口为 80 的数据包,攻击者实际上可以接收任何给 25 端口的数据包的解密,因为 TCP 协议栈会乐意解密给 25 端口的数据包,并把结果给正在监听的 Bob(这里Bob是攻击者),Bob会截获途中的数据包,防止数据包到达服务器,而他将修改这个数据包,将目标端口改为 25 ,这在密文里完成。然后,当这个数据包到达服务器时,目标端口说是 25 ,服务器会解密这个数据包,就把数据转发给了 Bob。现在,Bob通过改变目标端口,就可以读到本不该给他的数据。
如果数据使用的是带随机 IV 的 CBC 加密(这是一个 CPA 安全的机制)的,如果是这种情况,攻击者很容易改变密文以获得新密文,其目标端口是 25 ,而非80,攻击者只需修改IV域即可。事实上,其他的一切都保持不变,攻击者捕捉的是一个 CBC 加密的数据包,从这个数据包里,攻击者知道了目标端口是 80 ,但不知道数据是什么,他的目标是构建一个新的加密的数据包,其目标端口是 25 。攻击者只需改变 IV ,而解密 CBC 加密的数据的方法是,本质上,第一个明文分组是第一个密文分组的解密再与 IV 异或的结果,在原数据包里会读到目标端口为 80 ,那么攻击者该如何修改 IV 使得目标端口读起来是 25 ?容易看出,如果攻击者取原 IV 和 …80… 、…25… 异或,然后容易看出这个新的 IV’ 与原密文信息一并发发送,当攻击者解密时,新的 IV’ 会抵消掉 80 异或 25 将目标端口变成 25 。这个简单的方法,通过修改 IV 域,攻击者可以重定向数据包。
这个例子展示了,没有完整性(确保信息不被篡改),一个 CPA 安全的加密不可能提供私密性。如果攻击者可以在途中修改数据包,CPA 安全加密只能在攻击者只能窃听数据的这一假设下,提供私密性,但在例子中可以看到攻击者不能在途中修改密文(如果可以修改密文,一个简单的修改也会完全改变明文)。
选择密文攻击的例子
这是另外一个篡改攻击的例子,只需要能接收到网络流量即可,不需要攻击者在解密机器上操作。
有一个远程终端应用,每次用户敲击键盘,一个加密的键盘输入被送往服务器,我们假定键盘输入是使用计数器模式加密的,D 对应一个字节输入,每个 TCP/IP 包包含了一个校验和 T ,校验和只能使用于检测传输错误,如果服务器接收了一个含错误校验和的数据包,它就会简单地扔了这个包。现在攻击者想学习键盘输入的内容,他会截获这个数据包,不修改它,但他会记录下这个数据包,直接把包发给服务器,之后他会修改数据包,然后再把修改后的数据包发给服务器,他会把加密的校验和与一个值 t 异或,把加密的数据与一个值 s 异或,他用很多 t 和 s 来做这件事。计数器模式的一个性质是,如果你用 t 异或密文,解密后明文结果也是与 t 异或的。服务器解密这个修改后的数据包,得到的数据包有个异或了 t 的校验和,数据是异或了 s 的,如果修改的校验和对于这个修改的数据包来说是正确的,服务器会发送一个 ACK 应答包;如果不正确,服务器会扔掉这个数据包。所以攻击者可以根据能否收到 ACK 包学习到特定的 t 异或和 s 异或,是否对应一个有效的校验和,攻击者会学习到,如果我们修改了数据,把数据和特定值 s 异或,那么校验和就要与 t 异或,他学习到很多的 t 和 s 。根据如图所示方程,可以解出值 D 。这是一个很好的例子,被叫做选择密文攻击。
我们可以看到许多这种攻击的例子,攻击者可以修改途中的通信,以上两个例子叫做主动攻击。
以上两个例子可以证明,只提供 CPA 安全,或者说对抗窃听的安全,对抗主动攻击者时不能保证安全,不仅密文没有完整性,而且甚至连私密性也没有。CPA 安全密码并不提供认证加密。
如果你的信息只需要完整性,不需要私密性,使用 MAC 就足够了。
如果你的信息需要完整性,也需要私密性,那么必须使用认证加密模式。
CPA 安全模式不应该被使用在加密数据上,带随机 IV 的 CBC 可以为认证加密构建分组,但不应被单独使用。
Definitions
认证加密
认证加密:即存在主动攻击也能保持安全。认证加密是一个密码,通常是个加密算法,取密钥、信息为输入,还可选一个新鲜值,输出一个密文。解密算法通常是输出一个信息,但是这个解密算法可以输出一个特殊符号,叫做 底⊥ 。当解密算法输出符号 ⊥ 时,意味着密文是无效的,应当被忽略,唯一要求是这个 ⊥ 不在信息空间内,它表示密文应当被拒绝。
一个安全的认证加密系统
必须满足连个性质:
①这个系统必须对选择明文攻击是语义安全的。
②这个系统必须满足密文完整性。
这意味着,即使攻击者能看到许多密文,他也不应该能阐述另外一个能顺利解密的密文。
密文完整性游戏
这里 (E,D) 是一个信息空间 M 上的密码。通常,挑战者开始时选择一个随机密钥 k ,攻击者可以提交他选择的信息,收到这些信息的加密,如图,$c_1$ 是 $m_1$ 的加密,$m_1$ 由攻击者选择,攻击者可以反复这样操作,直到获得了 q 个信息的密文。他的目标是产生某个新的有效密文,如果这个攻击者产生的新密文被正确的解密了,即被解密成了不是符号 ⊥ 的东西,我们说攻击者赢得了游戏。通常我们定义在这个密文完整性游戏中,攻击者的优势为挑战者在游戏最后输出 1 的概率,如果事实上对所有的有效攻击者,其赢得游戏的优势都是可忽略的,我们说这个密码有密文完整性。
带随机 IV 的 CBC 不提供认证加密。因为对于攻击者来说,很容易赢得密文完整性游戏。攻击者提交一个密文,CBC 的解密算法从不输出符号 ⊥ ,他总是输出某些信息,攻击者轻松获得游戏胜利。(任何奇怪的随机密文都会被解密成某些不是符号 ⊥ 的东西。)
认证加密的两个影响
第一个影响—认证
认证,意味着攻击者无法欺骗接收方 Bob ,让 Bob 认为 Alice 发送了一条她没有发过的信息。如图,攻击者与 Alice 互动,让她去加密任意他选择的信息,这是一个选择明文攻击,攻击者的目标是产生某些不是由 Alice 创造的密文,因为攻击者不能赢下这个密文完整性游戏,他不能做到,意味着当 Bob 接收能被加密算法正确解密的密文时,他知道信息一定来自某知道密钥 k 的人。特别地,如果 Alice 是唯一知道 k 的人,那么他知道密文确实是来自 Alice ,并非攻击者发出的某些修改。
唯一剩下的警告是,认证加密无法抵抗重放攻击。攻击者可以截获某些从 Alice 到 Bob 的密文,攻击者可以重放信息,这样重放的密文对 Bob 来说看起来也是有效的。比如,Alice 让 Bob 转账100元,重放密文会反复进行转账,因此,任何加密协议必须能防御重放攻击,但这是认证算法能直接阻止得了的。
第二个影响—它能抵抗一种非常强力的攻击者,即实施选择密文攻击(下节讨论)。
Chosen ciphertext attacks
认证加密可以抵抗选择密文攻击。
前面讲过,攻击者有某个他想解密的密文 c ,攻击者可以欺骗解密服务器去解密某些密文,但这些密文还不是 c ,在这个例子里,攻击者可以获得特定密文的解密结果,但不会是全部的密文;在另一个例子里,攻击者可以通过提交密文给解密者来学到明文,在这个例子里,攻击者提交 TCP/IP 数据包给解密服务器,如果加密服务器发送 ACK 包,攻击者就知道了解密后的明文有一个有效的校验和,否则,解密后的明文没有有效的校验和。
为了解决选择密文攻击的威胁,我们定义一个非常广义的安全观点,叫做选择密文安全。在这里,攻击者可以进行选择明文攻击 CPA ,也可以进行选择密文攻击 CCA ,即,它可以获得他选择的任意信息的加密,也可以解密他选择的任意密文,而不是挑战密文。
在这个模型里,攻击者有特定的密文想解密,它可以与解密者互动,向解密者发送这些选择密文的询问,解密各种密文,除了挑战密文。攻击者的目标是破坏挑战密文的语义安全。
选择密文安全
通常,我们有一个密码 (E,D) ,我们将定义两个实验,实验0 和 实验1 。挑战者开始时选择一个随机密钥,现在攻击者提交询问给挑战者,每个询问可以是两种类型中的一种,可以是 CPA 也可以是 CCA 。
一个选择明文询问中,攻击者提交两个信息 $m_0$ 和 $m_1$ ,它们的长度相同,在 实验0 中,攻击者收到 $m_0$ 的加密结果,或者是,在 实验1 中,攻击者收到 $m_1$ 的加密结果。攻击者收到左边或右边的加密结果取决于我们是在 实验0 还是在 实验1 中。
一个选择密文询问中,攻击者提交他选择的任意密文,他获得密文的解密,唯一的限制是,他的密文不是选择明文攻击的询问中他所获得的密文之一。这不合理,因为攻击者可以通过 CPA 询问轻松获得密文,得到的是 $m_0$ 或 $m_1$ 加密的结果,如果攻击者可以提交特定密文的 CCA 询问,他会获得 $m_0$ 或 $m_1$ 作为答复,这样攻击者就会知道自己是在 实验0 还是 实验1 了。所以我们说,攻击者收到的 CPA 密文都是挑战密文,攻击者允许获得任何他选择的密文的解密结果,这些挑战密文除外。
通常,攻击者的目标是确定他是在 实验0 ,还是 实验1 。这是一个极为强大的攻击者,他可以获得除了挑战密文外,任意密文的解密结果,但他依然不能区分他是在 实验0 或 实验1 中,如果攻击者在 实验0 和 实验1 中表现一致,无法区分这两个实验,通常我们说密码是 CCA 安全(选择密文安全)的。
带随机 IV 的 CBC 不是 CCA 安全的
一个简单的例子来证明,带随机 IV 的 CBC 不是 CCA 安全的,为什么呢?
攻击者在一开始提交两个不同的明文 $m_0$ 和 $m_1$ ,我们假定这两个信息都是单分组的,然后攻击者会获得 $m_0$ 或 $m_1$ 的加密结果,注意,密文只有一个分组,因为明文只有一个分组长。攻击者要修改这个得到的密文 c ,变成 c’ ,他仅仅是将 IV 异或 1 。给一个新的不同于 c 的 密文 c’ ,因此攻击者完全可以提交 c’ ,作为他的选择密文攻击的询问,他让挑战者为他解密 c’ ,由于 c’ ≠ c ,挑战者必须解密 c’ ,c’ 的解密是什么?(如果我们把 IV 异或 1 ,明文也会异或 1 。)现在攻击者收到了 $m_0$⊕1,或是 $m_1$⊕1,攻击者就可以完全确定他在 实验0 ,还是在 实验1 ,攻击者的优势是 1 ,因为他可以轻松确定他在哪个实验。
一个定理
如果密码能够提供认证加密,这个密码就可以抵抗选择密文攻击。
如果我们有一个攻击者,提交了 q 个询问,换句话说,最多 q 个 CPA 询问和 q 个 CCA 询问,那么有两个有效的攻击者 $B_1$ 和 $B_2$ ,满足如下不等式:
由于这个机制有认证加密,
因为它是 CPA 安全的,因此不等式右侧第二个优势是可忽略的;
因为加密机制有密文完整性,因此不等式右侧第一个优势是可忽略的;
因此,攻击者赢得 CCA 游戏的优势,即不等式左侧的优势也是可忽略的。
上述定理的证明
如图,我们有两份 CCA 游戏,左上为 实验0 ,左下为 实验1 。攻击者提交 CPA 询问和 CCA 询问,最后他输出一个特定的猜测 b,记为 b’ ,我们的目标是证明这个 b’ 在两种情况下都是不可区分的。
首先,我们稍微改变一下挑战者,不再输出 CCA 询问的解密,攻击者会输出符号 ⊥ ,每次攻击者提交一个 CCA 询问,挑战者都说符号 ⊥ ,以下两个游戏在事实上是不可区分的,攻击者无法进行区分。因为机制有密文完整性,攻击者不能产生一个密文不是从 $c_1$ 到 c_i-1 中的,可以解密到不是符号 ⊥ 的其他东西。
同样的事情应用在下面的游戏中,可以知道左右两个游戏不可区分。
因为选择密文的询问总是以同样的方式回复,不会给攻击者任何信息,攻击者总是知道我们会以符号 ⊥ 回复,所以我们可以去除这些询问,得到下图。
去除这些询问后,剩下的游戏看上去很熟悉,即,右上和右下的游戏是由 CPA 安全的定义得来的,由于这个机制是 CPA 安全的,我们得出右上和右下的游戏不可区分,从而,我们证明了以上四个游戏都是等价的,因此,攻击者不能区分 实验0 和 实验1 ,因此这个机制是 CCA 安全的。
认证加密蕴含了对抗选择密文攻击的安全性。
认证加密的局限
①它不能阻止重放攻击。
②如果解密者透露了更多关于为什么密文被拒绝的信息,解密者不仅仅输出符号 ⊥ ,它还输出更多信息。如,计时攻击。
Constructions from ciphers and MACs
在软件项目中最常见的错误是不正确地组合加密和完整性机制。
CPA 安全加密和 MAC 的组合例子
在这三个例子里,有一个单独的密钥 $k_E$ 用来加密,一个单独的密钥 $k_I$ 用来 MAC ,这两个密钥相互独立,都是在会话建立阶段生成的。
第一个例子在 SSL 协议里,SSL 组合加密和 MAC ,希望能获得认证加密,组合方法如下:取明文 m 的 MAC ,使用 MAC 密钥 $k_I$ ,计算明文 m 的标签,然后把标签附在明文后面,然后加密这个明文和标签的联结,得到最终的密文。
第二个例子在 IPsec 中,取明文,首先加密这个明文,然后计算得到的密文的标签,把密文附在标签后。
第三个例子在 SSH 协议里,SSH 取明文,加密明文,计算明文的标签,把密文附在标签后。
试想,以上三个例子哪个是安全的?
在 SSH 方法中,标签是由明文计算的,然后把标签以明文的方式附在密文的后面,这存在很大的问题,因为 MAC 本身不是为私密性设计的,MAC 仅为完整性设计,事实上,仅以输出明文中的几位作为 MAC 的话,也没有错,也是很好的标签。如果使用这个方法,会完全破坏 CPA 安全性,因为明文的若干位在 MAC 签名算法的输出密文里被泄露了,所以这个 SSH 方法尽管对于 SSH 这个协议本身来说没有问题,也没有因为这个组合而被破解,但一般还是不建议使用这种方法。SSH方法有时叫做“加密且MAC”。
IPsec 的方法更为推荐,因为无论使用什么 CPA 安全系统和 MAC 密钥,组合总能提供认证加密。因为一旦我们加密了明文,明文的内容就被隐藏在密文里了,当我们计算密文的标签时,我们用这个标签给密文上了锁,确保没人能产生一个不同的密文看起来是有效的,因此保证了任何对密文的修改都会被解密者检测出来。IPsec有时叫做“先加密后MAC”。
在 SSL 方法中,有一些病态的例子,把 CPA 安全的加密系统和一个安全的 MAC 组合起来,结果却对一个选择密文攻击是脆弱的,所以 SSL 方法实际上不提供认证加密。这个发生的原因是,加密机制和 MAC 算法之间有一些不好的互动,事实上,会有一个选择密文攻击,因此 SSL 方法不提供认证加密。SSL 方法有时叫做“先MAC后加密”。(如果你使用随机计数器模式或随机 CBC,那么对那些 CPA 安全的加密机制,SSL 方法提供了认证加密,是安全的。事实上,如果你使用的是随机计数器模式,那么你的 MAC 算法只要是一次性安全的就够了,不需要是完全安全的 MAC,这样更高效。)
认证加密的三个标准模式
一旦认证加密的观念变得更为流行,很多组合加密和 MAC 的标准方法便涌现出来。
GCM(Galois计数器模式)和 CCM(CBC计数器模式)是由 NIST 标准化的。
GCM 的工作过程:使用了计数器模式加密,即使用 Carter-Wegman MAC 的随机计数器模式。GCM 的 Carter-Wegman MAC 如下工作,它是待求 MAC 的信息的一个哈希函数,然后用一个 PRF 加密哈希的结果,这个速度很快,而 GCM 的运行时间受制于计数器模式,为了更快,Intel 引入了一个特殊指令 PCLMULQDQ ,目标是让 GCM 的这个哈希函数跑得尽可能快。
CCM 的工作过程:使用 CBC MAC ,然后用计数器模式加密,这个机制使用 MAC ,然后加密。并不推荐使用。但因为使用的是计数器模式,实际上是一个很好的加密机制。CCM 一切都是基于 AES 的,它的 CBC-MAC 使用了 AES,他的计数器模式也是使用 AES ,因此,CCM 可以用相对少的代码实现,因为需要的仅为 AES 引擎,因此,CCM 被 WIFI 采用。
EAX 的工作过程:使用的是计数器加密模式,然后是 CMAC,先加密后 MAC 。
所有的这些模式都是基于新鲜值的,换句话说,它们不使用任何随机性,并且,每个密钥的新鲜值是唯一的,有序对(密钥,新鲜值)永远不应该重复使用,但新鲜值本身不一定是随机的,可以使用一个计数器。
所有的这些模式被称为带相关数据的认证加密(AEAD),这是一个认证加密的扩展,在网络协议中经常出现,AEAD 的想法是:提供给加密模式的信息不被完全加密,只有部分信息是被加密的,但所有信息是被认证的。网络数据包就是一个很好的例子,报文头不需要加密,封装数据需要加密,报文头和封装数据都需要被认证。
MAC 安全性的相关解释
安全MAC 定义的要求之一是,给定信息 m 的信息、MAC 对,攻击者不能产生同样的信息 m 的另一个标签,换句话说即使攻击者已经有了信息 m 的一个标签,他也不能产生同样信息 m 的一个新的标签。
为什么呢?如果攻击者已经有了信息 m 的一个标签,谁在乎他是否能产生另一个标签?
实际上,如果 MAC 没有这一性质,那么这个 MAC 会造成一个不安全的“先加密后MAC”的模式,如果想要“先加密后MAC”具有密文完整性,很重要的一点是,我们的 MAC 安全性蕴含着这个安全观点(即,不能产生同样信息 m 的一个新的标签)。
事实上,容易出现“产生新标签”这种伪造,在一种“先加密后MAC”系统有一种选择密文攻击,意味着它并不提供认证加密,如图所示,一开始,攻击者发送两个信息 $m_0$ 和 $m_1$ ,通常他会收到 $m_0$ 或 $m_1$ 的加密结果,由于我们使用“先加密后MAC”,攻击者收到的密文记为 $c_0$ ,$c_0$ 上有一 MAC t ,攻击者可以产生同样信息的另一个 MAC t’ ,于是他有了一个新的完全有效的密文 ($c_0$,t’) ,攻击者可以提交 c’ 的一个选择密文的询问,这是一个有效的选择密文的询问,因为它和 c 不同,挑战者将 c’ 的解密发送给攻击者,c’ 的解密为 $m_0$ 或 $m_1$ ,因此他能输出 b 的值,以优势 1 赢得这个机制。
由此证明,如果 MAC 安全性不蕴含着这个安全观点,那么在这个“先加密后MAC”系统有一种选择密文攻击,因此,它是不安全的。
OCB(由分组密码构建的认证加密机制)
如果考虑 MAC 和加密的组合是如何工作的,比如说计数器模式和 CMAC ,那么对每个明文分组,首先必须以计数器模式使用分组密码,然后必须再次使用分组密码运行 CBC-MAC ,这意味着,如果把 CPA 安全的加密和一个 MAC 组合起来,对每个明文分组必须计算分组密码两次,一次计算 MAC ,一次计算加密机制。
那么,我们能否由一个 PRP 直接构建一个认证加密机制?这样我们对每个分组只计算一次 PRP ,答案是肯定的,这个构造叫做 OCB 。OCB 比从加密和 MAC 分别构造的机制快很多。
如下图,在 OCB 里,我们输入明文,注意,OCB 是完全可并行的,每个分组可以被单独加密,另外,对每个明文分组,只需计算一次分组密码,然后在最后再计算一次分组密码,以构建认证标签,除去分组密码部分,OCB 的开销是最小的,只需要计算一个非常简单的函数 P ,新鲜值、密钥、分组计数器都给了 P 。
为什么 OCB 不是标准?OBC 没被应用的原因是各种各样的专利。。。
一些性能参数
如图,右边为不该用的模式的性能参数,因为它们只提供 CPA 安全,不提供对抗主动攻击的安全性。左侧为三种标准和 OCB 的性能参数。
GCM 虽然速度快,但在空间有限的硬件设备上,并不理想,因为它的实现需要更多的代码(Intel只需要很少代码)。
Case study:TLS
TLS 的工作过程
在 TLS 中,数据加密使用的协议叫做 TLS 记录协议,在这个协议栈,每个 TLS 记录都以一个报文头 HDR 开始,报文头后面接加密的数据,TLS 中记录的长度最多为 16KB ,如果需要发送多于 16KB 的数据,那么一个记录需要被拆分成多个记录。
现在,TLS 使用了单向密钥(从浏览器到服务器的单方向密钥),而从服务器到浏览器也有另一个密钥,服务器和浏览器双方都知道这两个密钥,两个密钥都是由 TLS 密钥交换协议生成的。
TLS 记录协议使用了所谓的基于状态的加密,意思是,每个数据包的加密是使用浏览器和服务器内部维护的特定状态来完成的。一些 64 位计数器,当会话被首次初始化后,这些计数器被初始化为 0 ,然后每次发送记录时,它们都增加。一个状态,两个计数器,这个状态存在于浏览器和服务器双方随着记录由以一方发送,另一方接收,状态被合理更新。
这些计数器的目的:阻止重放攻击。攻击者不能简单地保存记录,然后进行重放,因为计数器一定增加了。
TLS记录协议的工作细节
加密使用 AES-CBC ,MAC 使用 HMAC-SHA1 ,注意,TLS 使用了一个 MAC 然后加密。
浏览器给服务器发送数据,使用的是从浏览器到服务器的密钥,密钥本身是由 2 个密钥组成,一个 MAC 密钥 k_mac 和一个加密密钥 k_enc ,两个密钥在会话起始阶段就被协商好了,总的来说,从浏览器到服务器有 2 个密钥,从服务器到浏览器有 2 个密钥,一共有 4 个密钥。
TCL 数据包结构图如下。它以一个报文头开头,包含了数据包的类型、协议版本号以及数据包的长度。注意到数据包的长度是以明文形式发送的,加密数据、加密特定记录时,取密钥和当前状态为输入,工作流程如下:
①首先,计算数据的 MAC ,这是取 MAC 的实际的封装数据,报文头、计数器的当前值也在 MAC 的计算中。(所有计数器增加表示又一个记录被发送了。)即使计数器的值包含在标签里,注意,计数器的值实际上永远不会在记录中发送,它不用被放在记录里发送的原因是,另一端的服务器已经知道了计数器的值,所以不需要发送。这个标签计算的范围是三元组数据 [header,data,tag] 。
②把标签附在数据后面。由于是先 MAC 后加密,所以计算了 MAC 。我们会将数据和标签一并加密,所以报文头、数据和标签补齐到 AES 分组。
③用加密密钥来进行 CBC 加密。我们计算数据和标签的 CBC 加密,使用一个新鲜的随机 IV ,它会被嵌入到密文中。
④在结果前附上报文头、报文类型、版本号、长度,给出整个 TLS 记录,发送给服务器。
以上是 TLS “先MAC后加密”的实现,唯一与“先MAC后加密”的区别在于,有一个状态,即这个计数器,被包含在 MAC 值里。
为什么这个计数器能阻止重放攻击?
我们看记录协议是如何解密到来的记录,以加密的记录 record 为输入,服务器又将使用对应的、从浏览器到服务器密钥 以及 从浏览器到服务器的计数器。
①首先,我们使用加密密钥来解密记录。
②解密后,检测补齐长度,如果补齐格式错误,它将发送一个坏记录 MAC 警告并断开连接。如果需要发送更多记录,那就必须协商一个新的会话密钥。如果补齐格式正确,去除补齐很容易,服务器只需看补齐的最后的字节,然后进行相应的去除。
③从记录中提取标签,这个网页数据藏在这个去除补齐后剩下的记录里,然后验证报文头、数据和计数器值的标签,如果 MAC 不能验证,将发送一个警告“坏记录 MAC”,然后断开连接;如果标签通过验证,就去除标签、报文头,剩下的就是明文数据。
现在可以看到,如果记录被重放了(即,攻击者记下了某个记录重放给服务器),那时,计数器的值已经变了,因此被重放的记录的标签将不会通过验证。
这个方法“先MAC后加密”,不过只有当解密时没有信息泄露,才是认证加密。只要无法区分为什么密文被拒绝了(即,解密者暴露了拒绝的事实,但不说为什么拒绝),这就是一个认证加密系统。
当解密失败时,只要输出拒绝,永远不要解释为什么拒绝。在密码学里,如果解释为什么失败,很可能会造成一个攻击。
一个被破解的协议 802.11b WEP
802.11b WEP 工作流程:笔记本想发送一条信息给接入点,首先,笔记本计算信息的循环冗余校验码(CRC),然后把 CRC 校验码附在信息的后面,然后结果用流密码 RC4 加密。WEP 使用的密钥是一个初始 IV 值,这个 IV 每个数据包都会变,再联结上一个长密钥 k ,然后 IV 和密文一并传递给对方。
存在的两个问题:
①IV 会重复。可以实施一个二次密码本攻击。
②使用了关联非常密切的密钥。密钥仅仅是 IV 联结上 k ,唯一改变的是 IV ,而 k 总是固定的。RC4 不是为这种用法而设计的,会完全被破解。
攻击方法:
利用 CRC 校验和的一个性质,CRC 基本上是线性的,意思是如果我给你 CRC(m) ,可以很容易计算 CRC(m⊕p) ,只需要计算某个广为人知的函数 F(p) ,两者异或即可。异或从括号里提取出来,意味着 CRC 是线性的。
攻击如下,假设攻击者截获了某个送往接入点的数据包,现在数据包说,它的目标端口是 80 ,攻击者知道它是送往 80 端口的,攻击者想修改密文,使得目标端口变成 25 ,也许攻击者可以读取送往 25 端口的信息,CRC 校验和是为了确保攻击者不能修改密文中的数据,但事实上,非常容易修改密文数据,CRC 对篡改根本没有安全可言。
攻击者会对密文中代表 80 的那些字节异或某些特定的值 XX ,现在他会异或 25⊕80 ,如果异或特定字符串 XX 到密文里,密文由流密码生成,当密文解密时,此处的明文也会变成异或了 XX 后的样子,因此在解密后,这里的明文会变成 80⊕25⊕80=25 。
但是,如果我们只做这些,攻击还是会失败,因为 CRC 校验和现在还不是有效的,需要一个不同的 CRC ,但这不是问题,因为我们可以轻松修正这个 CRC 校验码,尽管 CRC 校验码也被加密了,我们把密文中对应 CRC 校验码的部分,与 F(XX) 异或,所以当密文解密后,我们会得到正确的 CRC 校验和。
结论:CRC 校验和完全不提供完整性来对抗主动攻击。
CBC padding attacks
一般情况下,当你想提供认证加密时,正确的方法是先加密,然后计算 MAC ,因为这样无论你组合什么加密和 MAC 算法,得到的结果将是认证加密。
假定这里的加密和 MAC 算法是正确实现的,我们看一个非常犀利的针对使用 CBC 加密的 TLS 记录协议的攻击。
TLS 解密时会发生两种错误:①补齐错误 ②MAC 错误
假设攻击者可以区分两种错误,得到的结果叫做补齐神谕。试想攻击者截获了一段特定的密文并试图去进行解密,它可以把这份密文提交给服务器,服务器会解密这段密文,然后检查补齐格式是否正确,如果补齐格式不正确,我们会得到一种错误类型;如果补齐格式正确,检查 MAC ,由于这段随机密文是攻击者捏造的,很可能是 MAC 错误的,然后攻击者会观测到一个 MAC 错误。所以如果补齐无效,我们会看到一个补齐错误;如果补齐有效,我们会看到一个 MAC 错误。因此,在向服务器提供密文后,攻击者可以知道解密的密文中最后几个字节是否是有效的补齐,这样攻击者仅仅通过提交密文给服务器,就学到了解密的密文中的一些信息。
那么,攻击者能否使用这个信息来完全解密一个给定的密文?一个补齐神谕,可以被用来完全解密一个给定的密文。
计时攻击
如果补齐无效,那么警告信息很快就会发出,在 21 毫秒内密文会被拒绝;如果补齐无效,检查 MAC ,发现 MAC 也是无效的,在 23 毫秒被拒绝,返回警告,即使返回同样的警告,攻击者可以观察警告信息生成的用时,如果时间较短,他就知道补齐是无效的,如果时间较长,他就知道补齐有效,MAC 无效。因此,攻击者有一个补齐神谕可以告诉他补齐是否有效。
如何利用补齐神谕?
如果攻击者有一个特定的密文 c ,它可以只使用补齐神谕就能完全解密这个密文。
假设攻击者想获取明文 m[1] ,这里有攻击者截获的密文,首先,他扔掉 c[2]
这样最后分组就是 c[1] ,即攻击者想解密的分组,现在假定他有一个特定的猜测 g ,对 m[1] 的最后一个字节进行猜测,g 是从0 到 255 的某个值。攻击者会计算 g⊕01,再异或分组 c[0] 的最后一个字节,当这两个密文分组被解密时,会发生什么?c[0] 被解密成什么我们不管,当 c[1] 被解密时,最后一个字节与这个修改的 c[0] 异或,得到明文的最后一个字节 将也是与这个多出来的、与 c[0] 异或的值 异或的,所以实际上原来明文 m[1] 的最后一个字节,现在与 g⊕01 异或了(图中0x表示十六进制)。
如果 m[1] 最后一个字节的猜测 g 是正确的,那么 last-byte⊕g 会抵消,last-byte⊕g=0,我们会得到明文的最后一个字节是 01 ,这意味着,如果我们对 m[1] 最后一个字节的猜测是正确的,那么我们获得了一个格式正确的补齐,补齐神谕说,这个补齐是有效的;如果猜测不正确,我们会得到一个不等于 1 的值,我们的补齐可能是无效的。可以看到,如果我们对 m[1] 最后一个字节的猜测是正确的,表示 g 实际上是正确的猜测;如果我们的猜测是错误的,g 就是错误的。
那么,攻击者会创建他的修改后的密文,注意,他只修改密文的第二个分组,把这个发送给补齐神谕,根据补齐神谕返回的结果,我们可以知道最后一个字节是否等于 g 。
我们可以重复这一步,g 从0 遍历到 255 ,直到找到正确的 g,我们就知道了 m[1] 的最后一个字节。然后,我们可以使用一模一样的流程来学到 m[1] 中倒数第二个字节,我们使用两字节的补齐 (02,02) ,这是一个正确的补齐格式。当我们用异或的技巧时,我们可以总是确保明文的最后一个字节为 02 ,现在我们可以猜测 m[1] 的倒数第二个字节了,通过尝试很多 g ,直到找到那个可以造出补齐 22 的 g 。然后一次次迭代这个过程。
这个攻击对于 TLS 不起作用,因为 TLS 接收到一个带有坏补齐或坏 MAC 记录时,它会关闭连接,然后重新协商一个新密钥,TLS 中只能提交一个询问,只会泄露单个询问的明文信息给攻击者,不会暴露整个明文分组。但这个攻击十分犀利,只要协议中有这样一个错误,攻击就会发生。
防御这个攻击的方法是始终检查 MAC ,因此需要花同样的反应时间,看补齐是否有效,无论补齐是否有效,就防止了计时攻击,让这个攻击更加困难。
两个教训
①如果 TLS 先加密后 MAC ,而不是先 MAC 后加密,这个攻击将完全不顶用。
②MAC 和 CBC 确实提供了认证加密,但仅当不透露解密失败的原因,但以上实验证实了这种模式不能提供认证加密。
Attacking non-atomic decryption
针对SSH的二元数据包协议的攻击
SSH 是一个标准的安全远程 shell 应用,使用了一个客户端与服务端之间的协议,它有一个密钥交换机制,一旦双方交换密钥,SSH 使用所谓的二元数据包协议来在客户端和服务端之间相互发送信息。
SSH工作过程:使用“加密且MAC”,每个 SSH 包以一个序列号开头,然后数据包包含了包的长度、CBC补齐的长度、封装数据、CBC补齐,图中红色快是用带链式 IV 的 CBC 加密的,所以这对 CPA 攻击也是脆弱的,计算整个数据包的明文的 MAC ,MAC 以明文的形式和数据包一起发送。SSH 解密过程如下:
①首先,服务器只解密加密的数据包的包长度域 packet len ,那么它只解密开头这几个字节。
②然后它从网络接着读取数据,读取的字节数由数据包长度域指定。
③SSH 使用 CBC 解密剩下的密文内容。
④一旦恢复了整个 SSH 数据包,它会接着检查明文的 MAC ,如果 MAC 无效,就报错。
这里的问题是,数据包长度域被解密了,然后被直接使用,以决定数据包的长度,这是在任何认证发生前,事实上,不可能认证数据包长度域的 MAC ,因为我们还没有还原整个数据包,所以我们还不能检查 MAC 。但是,SSH 协议在验证 MAC 之前就是用了数据包长度,这实际上引入了一个非常犀利的攻击。
我们只描述这个攻击的一个非常简化的版本,想法如下:假设攻击者截获了一个密文分组,即直接用 AES 加密的分组 m ,现在攻击者想还原 m ,这个截获密文只有一个 AES 分组长,攻击者向服务器发送一个数据包,数据包的开头是正常的,以一个序列号开头,然后他截获的密文 c 作为第一个分组,发送给服务器,服务器会解密第一个 AES 分组的前几个字节,他会把这前几个字节解读成数据包的长度域,接下来,服务器将期待着这么多字节,在验证 MAC 之前,攻击者将一次只给服务器一个字节,这样服务器会一个字节一个字节的读,最终,服务器会读到长度域里说的那么多的字节,他会检测 MAC 是否有效,由于攻击者给服务器的字节都是随便弄的,因此 MAC 不会通过验证,服务器会发送一个 MAC 错误,但是可以发现,攻击者在数他发送给服务器多少个字节,他能严格的知道他发送了多少个字节,当他接收到服务器发来的 MAC 错误,这就告诉攻击者,密文 c 的前 32 位的解密结果正好等于已经发送的字节数,在看到 MAC 错误之前,这是一个非常聪明的攻击,攻击者可以知道一条长信息的每个密文分组的高 32 位。
密码设计的两个错误:
①解密操作不是原子操作,换句话说,解密算法不取整个数据包作为输入,而返回整个明文作为输出,或者返回“拒绝”,解密算法部分地解密了密文,获得了长度域,然后等待指定数量的字节去还原,然后完成了解密过程。
②在正确的认证之前,就使用了长度域。
重新设计SSH,如何最小的改动,可以让SSH抵抗这种攻击?
方案①:以明文的形式发送一个长度域,就像 TLS 一样,这样,攻击者就没有机会提交选择密文攻击了,因为长度域不会被加密,攻击者无法滥用解密操作。
方案②:单独对长度域计算 MAC ,这样服务器可以去读长度域,检查仅为长度域服务的 MAC 是否有效,服务器就知道了接下来要读多少个字节,之后再检查整个数据包的 MAC 域。
方案③:可行,但效率极差,可能会让服务器遭受拒绝服务攻击。
Lesson