CBC 模式安全问题
CBC 模式,攻击者既可以攻击它的解密端,也可以攻击它的加密端,针对解密端的攻击,最常见的方式就是给定密文数据观测解密运算是成功还是失败
那么,解密端是怎么知道解密是成功还是失败呢?目前为止,我们唯一能够利用的就是数据补齐方案
一、数据补齐方案
如果一段数据只有 15 个字节,补齐的数据就只有这个标识字节,数值为 0,表示没有额外的补齐数据;如果有 14 个字节,标识字节为 1,表示还有一个字节的额外补齐数据,额外的补齐数据的数值也是 1;如果有 13 个字节,标识字节为 2,表示还有两个字节额外补齐数据,额外的补齐数据的数值也是 2;以此类推。
需要注意的是,如果一段数据有 16 个字节,也就是刚好一个数据分组大小,这时候,就需要一个全是补齐数据的数据分组,它的每一个字节都是 15。
二、补齐校验
那你会不会有疑问,我们如何在解密端,判断一个数据分组中的数据是不是补齐数据?
可以检查最后的几位数字是不是相同。比如说,如果最后一位是 2,但是倒数第二位和倒数第三位不是 2,解密就失败了。失败的原因,可能是由于篡改的密文分组,或者是篡改的初始化向量,或者是篡改的密钥。不管哪种原因,都可能导致补齐数据的校验失败。
那我们怎么利用数据补齐方案展开攻击呢?
三、解密端攻击-补齐预言攻击
在 CBC 模式的解密端,利用数据补齐方案,展开补齐预言攻击
回顾下 CBC 模式的解密过程,一个密文分组的解密,需要如下的输入数据:
上一次的密文分组 Ci-1
这一次的密文分组 Ci
密钥 K
接下来,我们利用数据补齐方案的攻击,通过修改、构造最后一个密文分组 Ci 的前一个密文分组 Ci-1,也就是倒数第二个密文分组,然后让解密端解密构造后的密文数据,观察修改了密文数据的解密能否成功
那倒数第二个密文分组该怎么构造?首先,修改该密文分组的最后一个字节,该字节可以从零开始,毫无疑问,解密端并不能正确解密该密文分组,得到的明文分组也不是期望的明文数据,但是,正像我们前面讨论的,解密端并没有办法知道这一个密文分组解密失败。要判断解密是否成功,还需要判断最后一个明文分组的补齐数据是不是符合规范
如果我们修改倒数第二个密文分组的最后一个字节,那么解密后的最后一个明文分组应该只有最后一个字节受到影响。如果这个解密后的字节是零,其他的数据会被解读为有效数据,这样就会通过补齐数据的校验,如果解密后的这个字节不是零,那么,补齐数据的校验就会失败,解密端就会报错。观察解密端的行为,攻击者就能了解到,这个构造的字节没有通过解密过程。如果观察到失败,攻击者就会调节最后一个字节的数值,比如数值加一,然后再次让解密端尝试解密。
一个字节只有 256 种可能性,最多尝试 255 次,一定会有一次尝试,补齐数据是 0x00
当攻击者观察到解密成功时,他能够掌握哪些数据?
倒数第二个密文分组最后一字节的原始数据:Ci-1[15] 和修改后的数据:Ci-1’[15]
最后一个明文分组的最后一个字节:Pi’[15] = 0x00
通过以上数据,攻击者就可以破解:
> Pi'[15] = 0x00 = Ti[15] ^ Ci-1'[15]
> => Ti[15] = Pi'[15] ^ Ci-1'[15] = Ci-1'[15]> =>> Pi[15] = Ti[15] ^ Ci-1[15] = Ci-1'[15] ^ Ci-1[15]
接下来的目标,就是破解 Pi[14]
Pi'[14] = Pi'[15] = 0x01Ci-1'[15] = Pi'[15] ^ Ti[15] = 0x01 ^ Ti[15],其中,Ti[15] = 上一次的 Ci-1'[15]
现在,逐一尝试 Ci-1’[14] 即可,同上
预测补齐数据的这一类破解方案,都可以叫做“补齐预言攻击”
CBC 模式如何规避补齐预言攻击?
和数据完整性校验的算法结合起来,而不是依赖补齐数据是否合法
四、加密端攻击-BEAST 攻击
BEAST 攻击可以通过保证初始化向量的唯一性和随机性进行防范,具体细节不在此处过多阐述,有兴趣的可以自行去了解