https://blog.youkuaiyun.com/shift_wwx/article/details/84256774
常用的填充模式至少有5种,不同的编程语言实现加密时用到的填充多来于这些方式或他们的变化。
1. 常用的填充形式
1. 1 填充数据为填充字节的长度
这种填充方式中,填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。假定块长度为8,原文数据长度9,则填充字节数等于0x07;如果明文数据长度为8的整数倍,则填充字节数为0x08。
填充字符串如下:
原文数据1:FF FF FF FF FF FF FF FF FF
填充后数据1:FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07
原文数据2:FF FF FF FF FF FF FF FF
填充后数据2:FF FF FF FF FF FF FF FF 08 08 08 08 08 08 08 08
1.2 填充数据为0x80后加0x00
这种填充方式中,填充字符串的第一个字节数是0x80,后面的每个字节是0x00。假定块长度为8,原文数据长度为9或者为8的整数倍,则填充字符串如下:
原文数据1:FF FF FF FF FF FF FF FF FF
填充后数据1:FF FF FF FF FF FF FF FF FF 80 00 00 00 00 00 00
原文数据2:FF FF FF FF FF FF FF FF
填充后数据2:FF FF FF FF FF FF FF FF 80 00 00 00 00 00 00 00
1.3 填充数据的最后一个字节为填充字节序列的长度
这种填充方式中,填充字符串的最后一个字节为该字节序列的长度,而前面的字节可以是0x00,也可以是随机的字节序列。假定块长度为8,原文数据长度为9或者为8的整数倍,则填充字符串如下:
原文数据1:
FF FF FF FF FF FF FF FF FF
填充后数据1:
FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 07
或
FF FF FF FF FF FF FF FF FF 58 B3 98 9B AD F4 07
原文数据2:
FF FF FF FF FF FF FF FF
填充后数据2:
FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 08
或
FF FF FF FF FF FF FF FF 32 58 B3 98 9B AD F4 08
1.4 填充数据为空格
这种填充方式中,填充字符串的每个字节为空格对应的字节数0x20。假定块长度为8,原文数据长度为9或者为8的整数倍,则填充字符串如下:
原文数据1:FF FF FF FF FF FF FF FF FF
填充后数据1:FF FF FF FF FF FF FF FF FF 20 20 20 20 20 20 20
原文数据2:FF FF FF FF FF FF FF FF
填充后数据2:FF FF FF FF FF FF FF FF 20 20 20 20 20 20 20 20
1.5 填充数据为0x00
这 种 填 充 方 式 中 ,填 充 字 符 串 的 每 个 字 节 为0x00。假定块长度为8,原文数据长度为9或者8的整数倍,则填充字符串如下:
原文数据1:FF FF FF FF FF FF FF FF FF
填充后数据1:FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00
原文数据2:FF FF FF FF FF FF FF FF
填充后数据2:FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00
在填充方式 4 和方式 5 中,由于缺少填充数据长度的标识信息,如果原文数据的后几个字节本身包括空格或0,将不能够准确移去填充的数据。因此使用这样的填充方式时,对原文数据有一定的要求。
2. 常用的填充方式
2.1 ISO10126Padding
与上面1.3 节的填充方式相对应。
2.2 PKCS5Padding
PKCS5Padding或PKCS7Padding是RSA公司的公钥密码学标准PKCS #5文档中定义的填充方式,与上面1.1 节中的填充方式相对应。
2.3 PKCS1Padding
PKCS1Padding 是RSA公司的公钥密码学标准PKCS #1文档中定义的填充方式,是RSA 算法实现加密操作常用的填充方式。
加密块是8 位字节串EB,它由块标记BT、填充块PS和数据D 组成。即EB=00 || BT || PS || 00 || D。其中BT 是一个标记字节,表示加密块的结构。BT 有 3 个值,00、01 和02,其中私钥操作为00 或01,公钥操作为02。PS 为填充数据,对于BT 为00,填充数据为0x00;对于BT 为01,填充为0xFF;对于BT 为02,填充为假散列生成的非0值。
PKCS#1(v1.5)中规定当RSA的密钥长度是1024b,如果使用PKCS1Padding填充,则原文数据最多117B。如果原文不满足长度要求,则在加密前需要进行填充。假定原文数据长度为96 B,则填充处理后字符串分别如下:
原文数据:
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 30 31 32 33 34
35 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 30 31 32 33
34 35 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 30 31 32
33 34 35
私钥操作,00型,填充后数据:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 ……
私钥操作,01型,填充后数据:
00 01 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 ……
公钥操作,02型,填充后数据:
00 02 58 DE B9 E7 15 46 16 D9 74 9D EC BE C0 EA B5 EC BB B5 0D C4 29 95 6C 18 17 BE 41 57 19 00
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 …
…
从填充后的数据可以看出,对于00型的私钥操作,要求原文数据必须不能包含0x00,或者知晓数据长度,否则将不能准确移去填充数据。因此在加解密操作中,常使用01型的私钥操作和02型的公钥操作。
3. 块大小设置
块的大小根据算法需求来决定。
例如,AES 的数据块是128bits,也就是16B,所以,块的大小是16字节。
例如,DES 的数据块是64bits,也就是8 B,所以,块的大小是8字节。
另外,填充模式一般针对的是块加密模式(分组加密模式),MD5、SHA等散列方式没有填充模式。
之前一篇博文 Android 中数据加密 ---- AES加密 中有个BlockEncryption类就设定了块大小。
在加密的时候使用的代码是:
byte[] buf = new byte[BUFFER_SIZE];
每一次用BUFFER_SIZE(实例中指的是 4096 byte),但是在解密的时候代码如下:
byte[] buf = new byte[roundUpBlockSize(BUFFER_SIZE)];
函数roundUpBlockSize() 在BUFFER_SIZE 基础上多加了16 byte,这就是块大小。
也就是说,每一次加密使用的是4096 字节的数据,但是解密的时候一定是4096 + 16 字节,因为最后的16字节是用来填充使用。
但是,在DES 中这部分的代码就需要改成 8 字节,应该DES 块大小是64bits,如果还是使用AES 中使用的16 字节,会报错:
javax.crypto.BadPaddingException: pad block corrupted
参考:
关于加密数据的填充方式的研究