0%

对称加密 工作模式 填充方式

概述

通过维基百科和博客,学习了对称加密的工作模式和填充方式,记录一下。

图源:一文搞懂对称加密:加密算法、工作模式、填充方式、代码实现

工作模式

ECB

最简单的加密模式即为电子密码本(Electronic codebook,ECB)模式。需要加密的消息按照块密码的块大小被分为数个块,并对每个块进行独立加密。


本方法的缺点在于同样的明文块会被加密成相同的密文块;因此,它不能很好的隐藏数据模式。

CBC

1976年,IBM发明了密码分组链接(CBC,Cipher-block chaining)模式。在CBC模式中,每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量。

CBC是最为常用的工作模式。它的主要缺点在于加密过程是串行的,无法被并行化,而且消息必须被填充到块大小的整数倍。解决后一个问题的一种方法是利用密文窃取。

注意在加密时,明文中的微小改变会导致其后的全部密文块发生改变,而在解密时,从两个邻接的密文块中即可得到一个明文块。因此,解密过程可以被并行化,而解密时,密文中一位的改变只会导致其对应的明文块完全改变和下一个明文块中对应位发生改变,不会影响到其它明文的内容。

PCBC

填充密码块链接(PCBC,Propagating cipher-block chaining)或称为明文密码块链接(Plaintext cipher-block chaining,是一种可以使密文中的微小更改在解密时导致明文大部分错误的模式,并在加密的时候也具有同样的特性。

PCBC主要用于Kerberos v4和WASTE中,而在其它场合的应用较少。对于使用PCBC加密的消息,互换两个邻接的密文块不会对后续块的解密造成影响。正因为这个特性,Kerberos v5没有使用PCBC。

CFB

密文反馈(CFB,Cipher feedback)模式类似于CBC,可以将块密码变为自同步的流密码;工作过程亦非常相似。该模式首先将前一个密文分组进行加密,再与当前明文分组进行XOR运算,来生成密文分组。同样CFB模式也需要一个IV。

OFB

输出反馈模式(Output feedback, OFB)可以将块密码变成同步的流密码。它产生密钥流的块,然后将其与明文块进行异或,得到密文。与其它流密码一样,密文中一个位的翻转会使明文中同样位置的位也产生翻转。这种特性使得许多错误校正码,例如奇偶校验位,即使在加密前计算,而在加密后进行校验也可以得出正确结果。

CTR

注意:CTR模式(Counter mode,CM)也被称为ICM模式(Integer Counter Mode,整数计数模式)和SIC模式(Segmented Integer Counter)。
与OFB相似,CTR将块密码变为流密码。它通过递增一个加密计数器以产生连续的密钥流,其中,计数器可以是任意保证长时间不产生重复输出的函数,但使用一个普通的计数器是最简单和最常见的做法。

使用简单的、定义好的输入函数是有争议的:批评者认为它“有意的将密码系统暴露在已知的、系统的输入会造成不必要的风险”。目前,CTR已经被广泛的使用了,由输入函数造成的问题被认为是使用的块密码的缺陷,而非CTR模式本身的弱点。

填充

为什么需要填充

块密码只能对确定长度的数据块进行处理,而消息的长度通常是可变的。因此部分模式(即ECB和CBC)需要最后一块在加密前进行填充。

CFB,OFB和CTR模式不需要对长度不为密码块大小整数倍的消息进行特别的处理。因为这些模式是通过对块密码的输出与明文进行异或工作的。最后一个明文块(可能是不完整的)与密钥流块的前几个字节异或后,产生了与该明文块大小相同的密文块。流密码的这个特性使得它们可以应用在需要密文和明文数据长度严格相等的场合,也可以应用在以流形式传输数据而不便于进行填充的场合。

位填充(Bit padding)

第一位为1,补0至块大小。

字节填充(Byte padding)

ANSI X9.23

最后一个字节为需要填充的字节长度值,其余位填充随机数(通常填充00

例:下例中,块大小为 8 字节,需要填充 4 字节(以十六进制表示)。

… | DD DD DD DD DD DD DD DD | DD DD DD DD 00 00 00 04 |

ISO 10126

最后一个字节为需要填充的字节长度值,其余位填充随机数:

… | DD DD DD DD DD DD DD DD | DD DD DD DD 81 A6 23 04 |

PKCS#5 和 PKCS#7

PKCS#7并未规定块大小。PKCS#5PKCS#7的子集,其块大小固定为8字节(64位)

所有字节均为需要填充的字节长度值

… | DD DD DD DD DD DD DD DD | DD DD DD DD 04 04 04 04 |

PS:由于AES的块大小是128,所以虽然在Java中是AES/CBC/PKCS5Padding,但用的实际上是PKCS#7

注意

输入数据本身已对齐时,也需要填充一块长度为块大小的数据。保证解密时能够区分边界(识别出padding并去除)。

ISO/IEC 7816-4

类似于位填充,第一个字节是80,补00至块大小。

ISO/IEC 7816-4 是包含文件系统的智能卡的通信标准,本身不包含任何密码规范。

Zero padding

未对齐填充00,对齐则不填充

None

不填充

适合C语言中的字符串(末尾有00),可以区分边界。

参考

分组密码工作模式
填充_(密码学)
Padding (cryptography)