关于PKCS5Padding与PKCS7Padding的理解

前言

在采用AES、DES等块加密时,有时需要对不满足一个整块(block)的部分需要进行填充,我们常用的填充的方式就包括ZeroPadding、PKCS5Padding与PKCS7Padding,这里面有什么区别呢。

填充方式的区别

ZeroPadding,数据长度不对齐时使用0填充,否则不填充。使用0填充有个缺点,当元数据尾部也存在0时,在unpadding时可能会存在问题。

我们这里主要讨论PKCS7Padding与PKCS5Padding。

这是RFC中关于PKCS7的具体填充过程:

Some content-encryption algorithms assume the input length is a multiple of k octets, where k is greater than one. For such algorithms, the input shall be padded at the trailing end with k-(lth mod k) octets all having value k-(lth mod k), where lth is the length of the input. In other words, the input is padded at the trailing end with one of the following strings:

              01 -- if lth mod k = k-1
           02 02 -- if lth mod k = k-2
               .
               .
               .
     k k ... k k -- if lth mod k = 0 

The padding can be removed unambiguously since all input is padded,including input values that are already a multiple of the block size,and no padding string is a suffix of another. This padding method is well defined if and only if k is less than 256.

(1)PKCS7Padding,

  假设每个区块大小为blockSize

  <1>已对齐,填充一个长度为blockSize且每个字节均为blockSize的数据。

  <2>未对齐,需要补充的字节个数为n,则填充一个长度为n且每个字节均为n的数据。

(2)PKCS5Padding,PKCS7Padding的子集,只是块大小固定为8字节。

两者的区别在于PKCS5Padding是限制块大小的PKCS7Padding

具体代码实现

按照以上的定义,我们用golang实现如下:

func PKCS7Padding(cipherText []byte, blockSize int) []byte {
   padding := blockSize - len(cipherText)%blockSize
   padText := bytes.Repeat([]byte{byte(padding)}, padding)
   return append(cipherText, padText...)
}

func PKCS5Padding(cipherText []byte) []byte {
   return PKCS7Padding(cipherText, 8)
}

在解密后,需要将填充的字符去掉,取最后一位即知道存在多少个补充位,实现如下:

func unpadding(src []byte) []byte {
    n := len(src)
    if n == 0 {
        return src
    }
    paddingNum := int(src[n-1])
    return src[:n-paddingNum]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章