5 - 块运算其他方面介绍

块运算其他方面介绍

我的博客

原书:《Understanding Cryptography: A Text book for Students and Practitioners》

从这章开始,参考的原文有了很多错误,因此本文也会有错误。

块运算不止是加密算法。它其实是多才多艺的。比如,我们可以用块运算实现不同类型的加密策略,我们也可以使用块运算来实现流运算。块运算也可以用来构建哈希函数,信息认证码 MACs,或者密钥建立协议。块运算也可以用来生成伪随机数。

5.1 使用块运算加密:操作模式

在前面,我们介绍了 DES、3DES 以及 AES 对数据块进行加密。实际应用中,我们通常不只是简单加密 8 字节或 16 字节的原文,比如加密一封邮件或计算机文件。有多种通过块运算加密长明文的方法。包括:

  • 电密码本模式 ECB
  • 密码块链模式 CBC
  • 密码反馈模式 CFB
  • 输出反馈模式 OFB
  • 计数模式 CTR

后面三种模式使用块运算做为流运算的构成部件。

上面物种模式都有一个共有目标:加密数据,以保证数据保密传输。在实践中,我们不仅需要数据地保密传输,还要保证接收者能够确定信息确实来自发送者。这称作认证,这也称作伽罗瓦计数模式GCM,让接收者确定信息是否由共享密钥的那位发送。另外,认证也允许接收者一方判断密文在传输过程中是否被修改。更多关于认证的信息,查看第十章。

ECB 与 CFB 模式需要原文的长度正好是块运算使用的块大小的整数倍。如果原文没有这样的长度,必须进行填充。在实践中有多种进行填充的方式。一种填充方式是首先填充一个 1,之后填充需要数量的 0。

5.1.1 电码本模式 ECB

ECB: Electronic Codebook Mode 模式是加密信息最直接的方式。接下来使用 \(e_k(x_i)\) 表示原文 \(x_i\) 使用密钥 \(k\) 使用任意一种块加密运算加密。令 \(e_k^{-1}(y_i)\) 表示对密文 \(y_i\) 使用密钥 \(k\) 解密。让我们假设块运算加密(解密)块的大小是 \(b\) 位。超过 \(b\) 位的信息被划分为 \(b\) 位的块。少于 \(b\) 位整数倍的信息填充到 \(b\) 位的整数倍。EBC 模式下的每一块加密都是单独进行的。块运算可以是 AES/3DES。

EBC 模式的加密与解密可以描述为:

定义 5.1.1 电码本模式

\(e()\) 表示对块长度 \(b\) 的块运算,令 \(x_i\) 以及 \(y_i\) 表示长度为 \(b\) 的位串,那么有:

加密:\(y_i = e_k(x_i),i\geq 1\)

解密:\(x_i = e_k^{-1}(y_i)=e_k^{-1}(e_k(x_i)),i\geq1\)

ECB 有一个优点。没有必要进行加密与解密之间的同步。如果接收者没能接收到所有加密的块,依然有可能解密收到的块。相似的,如果有位错误,错误位只会影响当前的块,而不会影响其他的块。而且,ECB 的块运算可以并行进行,可以进行高速加密,其他的模式比如 CFB 是不支持并行计算的。

不过,ECB 有它自己的缺点。ECB 加密模式是高度确定的。这意味着确定原文块,只要密钥不变,那么密文就是确定的。攻击者看密文就能够直接看出是否有相同的信息发送,从密文中推导出信息的这种方法就是负载分析。比如,如果在信息中存在固定的头部,这个固定的头部总会产生相同的密文。基于此,攻击者就能够确定什么时候发布了新的信息。还有一个缺点在于,原文加密块与块之间是互相独立的。如果攻击者重新对密文块进行组织,可能会拼成一个有效的信息,而这个重新组织不会被侦测到。在这里我们就提到了 ECB 模式面临的两个明显的攻击方式。

ECB 模式很容易受到替换攻击,因为一旦一个特定的原文与密文块的映射 \(x_i -> y_i\) 确定,就可以简单操作一系列的密文块。考虑下面的问题:

例 5.1 替换攻击

让我们假设两个银行之间进行着有线传输协议。每一个传输有五个段字段,发送银行的 ID 以及账户信息,接收银行的 ID 以及账户信息,交易的总价。我们假设现在每一个字段正好具有 16 字节的 AES 字节宽度的块运算。在两个银行之间的密钥不会经常改变。因为 ECB 的特性,攻击者可以利用它的特性,进行简单的块替换攻击。

1 2 3 4 5
发送银行 A 发送账户 # 接收银行 B 接收账户 # 总价 $

攻击细节如下:

  1. 攻击者奥斯卡,在 A 银行与 B 银行都开了一个账户
  2. 奥斯卡接入了两个银行之间的有线网络
  3. 奥斯卡重复从他在银行 A 的账户发送 $1 到他在银行 B 的账户,他观测网络上的密文。虽然他不能解密密文,但是他可以查看到重复的密文块。他将第一块、第三块以及第四块
  4. 因为两个银行并不会频繁更换密钥,通过与将后续信息与他保存的第一块、第三块信息做比较,奥斯卡可以辨别出所有从 A 银行发送给 B 银行的账户。他现在值需要简单替换第四块信息(使用奥斯卡的接收账户),这样,所有转账都会发送到奥斯卡在 B 银行的账户
  5. 奥斯卡快速将 B 银行账户的钱提取出来,跑路就可以了,飞飞飞飞飞

这个攻击有趣的点在于,不需要攻击这个算法就能够实现攻击了。因此,即便我们使用 256 位密钥长度的 AES 将一个信息块加密 1000 次,也不能避免被攻击。不过,虽然被攻击了,信息依然是保密的。攻击只是替换密文的一部分,这就是对信息完整性的攻击。通过信息认证码(MACs: Message authentication codes) 以及数字签名,可以保护信息的完整性。还有伽罗瓦计数器模式,是一种内建完整性校验的加密模式。

替换攻击会在密钥不经常更换的情况下发生,因此频繁更换密钥是一个好主意。

现在,我们看 ECB 模式的另一个问题。

例 5.2 在 ECB 模式中的位图加密(建议看原书确定这个例子介绍的详细信息)

ECB 模式的另一个缺点是,确定的原文将会映射到确定的密文。对图片像素点组合的加密依然能够模糊看到图片的信息。这是因为这张图片的背景有大量相同的块。

这个信息泄露的方式与上面的替换攻击是类似的,因为这两个例子都没有实际破解加密算法。

引入初始化向量 IV,可以增加加密的随机性。

5.1.2 密码块链模式 CBC

CBC: Cipher Block Chaining 模式下蕴含着两个主要思想。第一,加密的块是链接到一起的,密文 \(y_i\) 不仅依赖于原文块 \(x_i\),还依赖于前一个块的原文。第二,通过使用随机的初始向量 IV,加密被随机化。

密文 \(y_i\) 是原文块 \(x_i\) 的加密结果,它反馈给运算输入,并于接下来的原文块 \(x_{i+1}\) 进行异或。之后对这个异或结果进行加密,得到下一个密文 \(y_{i+1}\),再用它来加密 \(x_{i+2}\),以此类推。第一个原文块 \(x_1\) 没有前一个加密密文,因此引入了初始化向量 IV,以此来保证每一个 CBC 加密都是不可确定的。注意到第一个密文 \(y_1\) 依赖于原文 \(x_1\) 以及初始化向量 IV。第二个密文依赖于 IV,\(x_1\) 以及 \(x_2\)。第三个密文 \(y_3\) 依赖于 IV 以及 \(x_1\)\(x_2\) 以及 \(x_3\),以此类推。最后一个密文是所有原文块与 IV 的函数。

当解密 CBC 模式的密文块 \(y_i\) 时,我们必须逆转我们在加密侧做的两个操作。首先,我们使用解密函数 \(e^{-1}()\) 解密密码块。之后,我们需要再次与对应的密文块异或。这个表达式可以表示为 \(e_k^{-1}(y_i) = x_i \oplus y_{i-1}\)。如果第一个密文块 \(y_1\) 解密了,得到的结果必须与初始化向量 IV 进行异或,以获得原文 \(x_1\),既 \(x_1 = IV \oplus e_k^{-1}(y_1)\)。整个加密与解密过程可以描述为:

定义 5.1.2 CBC 模式

\(e()\) 为块大小为 b 的块加密运算,\(x_i\) 以及 \(y_i\) 为长度为 b 的位串,IV 为长度为 b 的初始向量

加密(第一块):\(y_1 = e_k(x_1 \oplus IV)\)

加密(其他块):\(y_i = e_k(x_i \oplus y_{i-1}),i \geq 2\)

解密(第一块):\(x_1 = e_k^{-1}(y_1) \oplus IV\)

解密(其他块):\(x_i = e_k^{-1}(y_i) \oplus y_{i-1},i \geq 2\)

下面我们验证上面的定义,对第一块有:

\[d(y_1) = e_k^{-1}(y_i)\oplus IV = e_k^{-1}(e_k(x_1\oplus IV))\oplus IV = (x_1 \oplus IV)\oplus IV = x_1 \]

对于其他的块有:

\[d(y_i) = e_k^{-1} \oplus y_{i-1} = e_k^{-1}(e_k(x_i\oplus y_{i-1}))\oplus y_{i-1} = (x_i\oplus y_{i-1})\oplus y_{i-1} = x_i \]

如果我们在每次加密时都选择新的初始向量 IV,对于同样的原文,使用不同的初始化向量,加密后得到的密文将会完全不同。我们不需要对 IV 进行保密。大多数情况下,我们希望 IV 只使用一次。最简单的情况,在进行加密通讯之前选择随机数给到通讯的双方。备选方案是,交互双方已知一个计数值,每次新会话发生前自动加一。也可以使用交互双方的 ID 比如 IP 地址与当前时刻组合做为 IV。只要保证 IV 是不可预测的即可。

现在,让我们回头再看一下之前的银行攻击。通过合理地为每次有线传输选择 IV,攻击者因为不能识别到密文中的模式,无从进行希望地攻击。如果 IV 在几次传输时保持一致,攻击者可以识别到从他银行账户 A 发送给银行账户 B 的传输。但是,当他将他的密文 4 替换其他跑在 A 与 B 之间的有线传输时,银行 B 解密块 4 与 5 将会得到一些随机值。虽然钱不会按照攻击者的意图,去向他自己的账户,但也有可能去向其他人的账户,去向那个账户的钱也是不确定的。这对于银行而言,当然也是不能接受的。这个例子,展示了即便攻击者不能执行他期望的操作,但他更换后的密文,解密出的原文也更改了原意。因此,在现实世界的系统中,仅仅加密本身还是不够的:我们还必须保证信息的完整性。这可以通过信息认证码 MACs 或数字签名实现,后面会在第 12 章介绍。下面描述的伽罗瓦计数值模式可以同时提供加密以及完整性校验。

5.1.3 输出反馈模式 OFB

在输出反馈模式 OFB: Output Feedback Mode 中,块运算用来构建流运算加密策略。注意到,在 OFB 模式中密钥流不是按位产生的,而是以块的形式生成的(建议看原书中的配图)。块运算对密钥 k 处理给到处理后的比特流,用它与原文异或。

在 OFB 模式背后的机理是十分简单的。我们使用 IV 启动一个块运算,块运算输出给到我们密钥输出比特流,下一个密钥比特流是通过将上一个密钥比特流反馈给块运算并使用快运算加密它生成新的密钥流,以此类推。

OFB 模式形成一个同步流运算,因为密钥流不依赖于原文或密文。实际上,使用 OFB 模式与使用一个标准的流运算如 RC4 或 Trivium 是类似的。因为 OFB 模式可以视作一个流运算,加密与解密的操作使用的是相同的操作,接收者不需要使用逆转模式去解密密文。这是因为,实际的加密操作是通过异或操作实现的,逆转操作只需要再次进行异或即可。这样的操作是与 ECB 以及 CBC 模式是不同的,在这两个模式下,运算是块运算。

在 OFB 策略下加密与解密流程如下:

定理 5.1.3 输出反馈模式 OFB

\(e()\) 为一个块运算,块的长度为 b;令 \(x_i\)\(y_i\) 以及 \(s_i\) 为长度为 b 的比特流;IV 为只用一次长度为 b 的初始向量。

加密(第一块):\(s_1 = e_k(IV),y_1 = s_1 \oplus x_1\)

加密(其他块):\(s_i = e_k(s_{i-1}),y_i = s_i \oplus x_i,i \geq 2\)

解密(第一块):\(s_1 = e_k(IV),x_1 = s_1 \oplus y_1\)

解密(其他块):\(s_i = e_k(s_{i-1},x_i = s_i\oplus y_i,i \geq 2)\)

因为使用了初始化向量 IV,OFB 加密也是不可预测的,因此加密不同的原文可以得到不同的密文。OFB 模式的一个优点是,块运算是与原文相互独立的,因此,我们可以预先计算出多个后续要用的密钥流以备使用。

5.1.4 密文反馈模式 CFB

密文反馈模式 CFB: Cipher Feedback 也使用块运算来形成流运算。它与 OFB 模式相似,但是 CFB 是将密文反馈生成下一个密钥流。在 OFB 模式中,密钥流不是按位生成的,而是按块生成的。首先,我们使用密钥块加密初始向量 IV 得到第一块密钥流 \(s_1\),后续的密钥流块 \(s_2,s_3,...\),我们使用之前生成的密文加密得到。

因为 CFB 模式形成一个流运算,加密与解密使用相同的操作。CFB 模式是异步流加密的例子。因为流运算输出也是密文的函数。

下面描述了 CFB 模式:

定义 5.1.4 密文反馈模式 CFB

\(e()\) 为一个块运算,块的长度为 b;令 \(x_i\)\(y_i\) 是长度为 b 的比特流,IV 为只用一次的长度为 b 的初始向量。

加密(第一块):\(y_1 = e_k(IV) \oplus x_1\)

加密(其他块):\(y_i = e_k(y_{i-1}) \oplus x_i,i \geq 2\)

解密(第一块):\(x_1 = e_k(IV) \oplus y_1\)

解密(其他块):\(x_i = e_k(y_{i-1}) \oplus y_i,i\geq 2\)

因为使用了初始化向量 IV,CFB 加密也是不可预测的。

CFB 的一个变体可以用在短原文块的加密。比如可以用在键盘与计算机之间的加密。由远程键盘生成的原文通常只有 1 字节长度既 ASCII 码。在这个情况下,只有 8 位的密钥流来加密,密文也只有 1 字节。

5.1.5 计数器模式 CTR

另一个使用块运算应用在流运算的模式是计数器模式 CTR: Counter Mode。就像 OFB 以及 CFB 模式一样,CTR 的密钥流也是按块计算得到。给到块运算模块的输入,是一个计数器,每次都将新的值给到块运算来生成密钥流块。

我们必须小心地初始化块运算的输入,以防止使用相同的输入两次。否则,如果攻击者知道两个原文使用了相同的输入加密,他可以计算密钥流块,这样马上就可以解密其他密文。为了实现这样的唯一性,实践中通常使用下面的方法。假设块运算的输入宽度为 128 位,比如 AES。首先我们选择一个初始向量 IV 长度短于块长度,96 位,剩下的 32 位初始为 0 以待后续计数器使用。对于每一个在会话中加密的块,IV 保持不变,计数器增加。在这个例子中,选中一个 IV 之后,我们可以加密 \(2^{32}\)个块。(问题) 因为每一个块由 8 字节组成,最多可以加密 \(8 \times 2^{32} = 2^{35}\) 字节的数据,既选中一个初始化向量 IV 可以加密约 32GB 的数据再更换新的向量。下面是计数器模式的正式描述:

定义 5.1.5 计数器模式 CTR

\(e()\) 为一个块运算,块的长度为 b;令 \(x_i\)\(y_i\) 是长度为 b 的比特流,初始化向量 IV 与计数器 CTR 的串联表示为 \((IV||CTR_i)\) 是一个长度为 b 的位串。

加密:\(y_i = e_k(IV||CTR_i)\oplus x_i,x\geq 1\)

解密:\(x_i = e_k(IV||CTR_i) \oplus y_i,i \geq 1\)

注意到 \((IV||CTR_1)\) 是不需要保密的,它可以与第一个密文块一起发送。计数器 CTR 可以是常规的整数计数器,也可以是 LFSR。

看到这里,我们可能会疑惑为什么会有这么多的模式。计数器模式的一个吸引人的特点是,它可以并行计算,因为不像 OFB 或 CFB 模式,它不需要任何反馈。

5.1.6 伽罗瓦计数器模式 GCM

伽罗瓦计数器模式 GCM: Galois Counter Mode 在加密时也会计算一个信息认证码 MAC: Message authentication code。信息认证码由发送者计算并附加到信息上,提供校验和信息。接收者接收到信息之后,也会计算信息的 MAC 值,并检验计算得到的 MAC 值是否与发送的 MAC 值相同。这样,接收者就能够确定信息是由发送者发送,且没有其他人干预这条信息。这两个特性分别称作信息认证与信息完整性。关于 MAC 的信息将在 12 章详细介绍。下面我们先以 GCM 模式简单介绍。

GCM 使用计时器模式的加密来保证原文 x 的保密性。另外,GCM 不仅仅保护对原文的认证,也会认证字串 AAD: additional authenticated data 附加认证数据。在实践中,AAD 可能包含网络协议中的地质与参数。

GCM 由块运算与伽罗瓦域乘法器组成,利用这个乘法器实现了认证加密以及认证解密 GCM 函数。运算的块大小为 128 位长,比如 AES。在发送侧,GCM 使用 CTR 模式加密,接下来计算 MAC 值。在加密时,首先使用初始向量 IV 以及序列号初始化计数器;然后,初始计数器值会增加,这个值加密并于第一个原文块进行异或;对于后续的原文,计数值增加并加密。注意到,接下来的块运算只在加密模式下使用。如果初始向量已知,GCM 允许预计算块运算函数。

对于认证,GCM 进行一个链式伽罗瓦域乘法。对于每一个原文 \(x_i\),生成中间认证参数 \(g_i\)\(g_i\) 是当前密文 \(y_i\) 以及 \(g_{i-1}\) 的异或和,之后 \(g_i\) 与常量 H 做乘法。常量 H 是哈希子密钥,通过对全零的输入的块加密得到。所有乘法都遵循 128 位的伽罗瓦域 \(GF(2^{128})\) 其中不可约多项式为 \(x^{128} + x ^7 + x^2 + x + 1\)。因为每一个块运算加密只需要一次乘法操作,GCM 模式只需增加少量的计算。

定义 5.1.6 基础伽罗瓦计数器模式 GCM

\(e()\) 为一个块运算,块的长度为 128 位;\(x\) 为由块 \(x_1,...,x_n\) 组成的原文;令 AAD 做为附加认证数据。

加密

a. 从 IV 中获取到计数器值 \(CTR_0\),并计算 \(CTR_1 = CTR_0 + 1\)

b. 计算密文 \(y_i = e_k(CTR_i)\oplus x_i,i\geq 1\)

认证

a. 生成认证子密钥 \(H = e_k(0)\)

b. 计算 \(g_0 = AAD \times H\)

c. 计算 \(g_i = (g_{i-1}\oplus y_i)\times H,1\leq i \leq n\)

d. 最终证签 \(T = (g_n \times H) \oplus e_k(CTR_0)\)

接收者接收到包 \([y_1,...,y_n],T,ADD]\) 之后,通过计数器模式解密密文。为了检验数据的认证,接收者使用接收到的密文以及 \(ADD\) 做为输入计算证签 \(T'\)。如果 \(T\)\(T'\) 一致,那么接收者可以说密文及 ADD 在传输过程中没有被修改。

5.2 再看穷举密钥搜索

在小节 3.5.1 中,我们可以看到,给定一个原文-密文对 \((x_1,y_1)\),DES 密钥可以通过使用下面简单的算法进行穷举搜索:

\[DES_{k_i}(x_1) = y_1,i = 0,1,...,2^{56}-1 \]

对于某些块运算,密钥搜索会更加复杂。有时,暴力攻击可能出现错误地正向结果,既,密钥 \(k_i\) 找到了,但是并不是真正的密钥,这个找到的结果,只在这一个特例下成立。这与密钥空间以及原文空间有关。

虽然有上面的情形,暴力破解攻击依然是有可能的,但是需要多对原文-密文对。在尝试所有可能的密钥后,只有一个密钥是正确的。

让我们看一下为什么一个密钥对 \((x_1,y_1)\) 可能不足以确定正确的密钥。假设有一个运算,块长度为 64 位,密钥长度为 80 位。如果我们在所有可能的 \(2^{80}\) 密钥下加密 \(x_1\),我们可以得到 \(2^{80}\) 密文。然而,只有 \(2^{64}\) 个是不同的,因此一些密钥必然会将 \(x_1\) 映射到相同的密文。如果我们对给定的原文-密文对,编历所有的密钥,我们可以找到 \(2^{80}/2^{64} = 2^{16}\) 个密钥,可以实现 \(e_k(x_1) = y_1\) 的映射。这个估计是有效的,因为,给定一个密钥,对原文的加密可以看作是随机选择一个 64 位的密文字串。

在这 \(2^{16}\) 个候补密钥中 \(k^{(i)}\) 是用来加密的那个密钥。让我们称之为目标密钥。为了确定那个目标密钥,我们需要第二个原文-密文对 \((x_2,y_2)\)。对于这个原文-密文对,也存在 \(2^{16}\) 个可能的密钥候补。它们中的其中一个是目标密钥。其他的密钥可以视作对可能密钥的随机选择。目标密钥必然同时存在于这两个可能的集合中。为了确定暴力破解的效率,关键的问题是:两个集合中共同包含的错误密钥集是什么。

定理 5.2.1 给定一个具有 \(\kappa\) 位密钥长度的的块运算,块长度为 n 位,并有 t 个原文-密文对 \((x_1,y_1),...,(x_t,y_t)\),可以将原文加密为密文的错误密钥是:

\[2^{\kappa - tn} \]

回到我们的问题,假设两个原文-密文对,可能的错误密钥 \(k_f\) 能够同时实现 \(e_{k_f}(x_1) = y_1\)\(e_{k_f}(x_2) = y_2\) 是:

\[2^{80-2\dot 64} = 2^{-48} \]

这个值是如此小,在实践中,两个原文-密文对就足够进行暴力破解了。如果攻击者知道三个原文-密文对,约有 \(2^{80-3\dot 64} = 2^{-112}\) 可能错误密钥。

5.3 增强块运算的安全性

5.3.1 双重加密以及中间相遇攻击

假设有一个块运算,密钥长度为 \(\kappa\) 位。对于双重加密,原文 \(x\) 首先使用密钥 \(k_L\) 加密,得到的结果再使用第二个密钥 \(k_R\) 加密。

一个幼稚的暴力破解方法是,搜索所有可能的密钥组合,密钥长度将会是 \(2\kappa\),暴力破解将需要 \(2^{\kappa} \cdot 2^{\kappa} = 2^{2\kappa}\) 次加密/解密计算。不过,通过使用中间向于攻击,密钥空间可以显著降低。首先暴力攻击左侧的加密,再攻击右侧加密。这样只需要 \(2^{\kappa} + 2^{\kappa} = 2^{\kappa + 1}\) 次计算。

攻击具有两个步骤,首先暴力攻击左侧的加密,计算得到一个查询表。第二步攻击者尝试在表中查找一个可用的解。

5.3.2 三重加密

相比于双重加密,更加安全的方式是加密块数据三次:

\[y = e_{k_3}(e_{k_2}(e_{k_1}(x))) \]

在实践中,通常使用三重加密的一个变体:

\[y = e_{k_3}(e_{k_2}^{-1}(e_{k_1}(x))) \]

这个类型的三重加密一般称作 EDE。使用它没有任何安全方面地考量。只因为若选择 \(k_1 = k_2\),那么等效于:

\[y = e_{k_3}(x) \]

5.3.3 密钥漂白

密钥漂白的策略如下。相较于常规的密钥 \(k\),两个密钥 \(k_1\) 以及 \(k_2\) 用来与原文、密文进行异或:

定义 5.3.1 块运算的密钥漂白

加密:\(y=e_{k,k_1,k_2}(x) = e_k(x\oplus k_1)\oplus k_2\)

解密:\(x = e_{k,k_1,k_2}^{-1}(y) = e_k^{-1}(y\oplus k_2)\oplus k_1\)

密钥漂白不会增强块运算应对分析攻击的能力。在这一点上,它与多重加密正相反,多重加密是可以增强应对分析攻击的能力。

posted @ 2023-03-14 20:38  ArvinDu  阅读(49)  评论(0编辑  收藏  举报