算法还原之对称加密模式及填充
一 前言
根据上节课DES的加密流程,利用CyberChef来测试
会发现除了输入plainText 和 key之外,还需要选择模式Mode和偏移量iv:
上面是ECB模式,默认可以不输入iv,但是将Mode修改为CBC后,就会报错。要求必须输入iv的值
根据上节课的原理,要求输入的明文必须为64位/64位的倍数。但是这块将输入调整为 “1234567”,56位,发现也是可以正常加密的
这块是因为当输入明文不满足64位的倍数的时候,会对明文的长度进行填充。。。
二 加密模式
加密模式可以简单理解为,在加密前/加密后,对用户的输入/输出进行处理。分组密码常见的加密方式主要有5种:
- ECB:电子密码本模式(不需要传入iv)
- CBC:密码块链接模式
- CFB:密文反馈模式
- OFB:输出反馈模式
- CTR:计数器模式
明文分组是指分组密码算法中作为加密对象的明文。明文分组的长度与分组密码算法的分组长度是相等的。
密文分组是指使用分组密码算法将明文分组加密之后所生成的密文。
ECB模式
在ECB模式中,将明文分组加密之后的结果将直接成为密文分组。
ECB模式的加密:
ECB模式的界面:
ECB模式中,明文分组和密文分组是一一对应的关系,因此,如果明文中存在多个相同的明文分组,则这些明文分组最终将被转换为相同的密文分组。
整个过程不需要iv参与。
安全性低,易攻击。
CBC模式
CBC模式的密文分组像链条一样相互连接在一起。
在CBC模式中,首先将明文分组与前一个密文分组进行XOR运算,然后再进行加密。
CBC模式的加密
CBC模式的解密
初始化向量
当加密第一个明文分组时,由于不存在“前一个密文分组”,因此需要事先准备一个长度为一个分组的比特序列来代替“前一个密文分组”,这个比特序列称为初始化向量,通常缩写为IV。一般来说,每次加密时都会随机产生一个不同的比特序列来作为初始化向量。
- 假设CBC模式加密的密文分组中有一个分组损坏了,例如由于硬盘故障导致密文分组的值发生了改变等,这种情况下,只要密文分组的长度没有发生变化,则解密时最多只会有2个分组收到数据损坏的影响。
- 假设CBC模式加密的密文分组中有一些比特缺失了,例如由于通信错误导致没有收到某些比特等,那么此时即使缺失1比特,也会导致密文分组的长度发生变化,此后的分组发生错位,这样一来,缺失比特的位置之后的密文分组也就全部无法解密。
填充提示攻击是一种利用分组密码中的填充部分来进行攻击的方法。在分组密码中,当明文长度不为分组长度的整倍数时,需要在最后一个分组中填充一些数据使其凑满一个分组长度。在填充提示攻击中,攻击者会反复发送一段密文,每次发送时都对填充的数据进行少许改变。由于接收者(服务器)在无法正确解密时会返回一个错误消息,攻击者通过这一错误消息就可以获得一部分与明文相关的消息。这一攻击模式并不仅限于CBC模式,而是适用于所有需要进行分组填充的模式。
CFB模式
在CFB模式中,前一个密文分组会被送回到密码算法的输入端。所谓反馈,这里指的就是返回输入端的意思。
CFB模式的加密
CFB模式的解密
在ECB模式和CBC模式中,明文分组都是通过密码算法进行加密的,但在CFB模式中,明文分组并没有通过密码算法来直接进行加密。在CFB模式中,明文分组和密文分组之间只有一个XOR。
在生成第一个密文分组时,由于不存在前一个输出的数据,因此需要使用初始化向量(IV)来代替,与CBC模式相同。
OFB模式
在OFB模式中,密码算法的输出会反馈到密码算法的输入中。
OFB模式并不是通过密码算法对明文直接进行加密的,而是通过将“明文分组”和“密码算法的输出”进行XOR来产生“密文分组”的,这点与CFB模式相似。
OFB模式的加密
OFB模式的解密
OFB模式和CFB模式的区别仅仅在于密码算法的输入。
CFB模式中,密码算法的输入是前一个密文分组,也就是将密文分组反馈到密码算法中,因此被称为“密文反馈模式”;
OFB模式中,密码算法的输入是密码算法的前一个输出,也就是将输出反馈给密码算法,因此被称为“输出反馈模式”。
CTR模式
CTR模式是一种通过将逐次累加的计数器进行加密来生成密钥流的流密码。最终的密文分组是通过将计数器加密的到的比特序列,与明文分组进行XOR而得到的。
CTR模式的加密
CTR模式的解密
计数器的生成方法,前8个字节为nonce,这个值在每次加密时必须时不同的。后8个字节为分组序号,这个部分逐次累加。
OFB模式与CTR模式的对比
- 两者都是流密码。
- OFB模式是将加密的输出反馈到输入,CTR模式是将计数器的值用作输入。
CTR模式的特点:
CTR模式的加密华为解密使用了完全相同的结构;可以以任意顺序对分组进行加密和解密;可以实现并行计算;在支持并行计算的系统中,CTR模式速度非常快。
分组密码模式比较表
三 填充方式
正常按照DES算法来说,输入一个8个字节的明文字符串,输出的也应该是一个8个字节密文的。但很显然,在cyberchef中输出了18位的内容。
这个是什么原因呢????
还有一个,DES算法要求输入的明文必须为64位/64位的倍数。但是这块将输入调整为 “1234567”,7个字节,发现也是可以正常加密的,并且输出密文长度为8个字节:
这块又是什么原因呢???
分组密码中,需要将明文按指定大小进行分组,由于明文并非指定大小的整数倍,因此在明文的最后一个分组需要将其填充至加密算法所要求的分组大小后进行加密。
在解密时,按照同样的填充模式将填充的数据去除。常见的填充方式有以下6种:
- NoPadding
- PKCS#5
- PKCS#7
- ISO 10126
- ANSI X9.23
- ZerosPadding
NoPadding
不填充,在此填充下原始数据必须是分组大小的整数倍,非整数倍时无法使用该模式
PKCS#5
填充至符合块大小的整数倍,填充值为填充数量数(缺几个字节就填几个缺的字节数)
- 原始:FF FF FF FF FF FF FF FF FF
- 填充:FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07
比如这块原始长度为9个字节,确少7个字节为8的倍数,则填充值为 “07”
【注意】如果数据不缺省,也需要填充一个块长度的 0x00,如下所示:
- 原始:FF FF FF FF FF FF FF FF
- 填充:FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00
目的:为了更明确哪些内容是原始数据,哪些是填充的。如果有16个字节的原文为FF FF FF FF FF FF FF FF FF FF FF FF FF 03 03 03 ,那这块的03就不能区分是原始数据部分还是填充部分了。
如果填充了一个块长度的 0x00,就可以明确此处的03为原始数据部分。
PKCS#7
缺几个字节就填充几个缺的字节数(255 bytes)
如果数据缺省,也需要填充一个块长度的0x08
【注意】在AES加密当中严格来说是不能使用pkcs5的,因为AES的块大小是 16bytes 而PKCS#5只能用于8 bytes。通常在AES中所说的PKCS#5就是PKCS#7
ISO 10126Padding
填充至符合块大小的整数倍,填充值最后一个字节为填充的数量数,其他字节随机处理
- 原始:FF FF FF FF FF FF FF FF FF
- 填充:FF FF FF FF FF FF FF FF FF 3F 7A B4 09 14 36 07
ANSI X9.23
填充至符合块大小的整数倍,填充值最后一个字节为填充的数量数,其他字节填 0
- 原始:FF FF FF FF FF FF FF FF FF
- 填充:FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 07
ZeroByte Padding
填充至符合块大小的整数倍,填充值为 0
- 原始:FF FF FF FF FF FF FF FF FF
- 填充:FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00
如果已经是128bit的倍数,仍需要填充。