分组密码数据填充方式

文章介绍了在加密过程中用于调整明文长度的三种填充方式:PKCS7、ISO7816和X923。PKCS7填充在各个加密算法中广泛应用,填充值由填充字节数决定;ISO7816填充以0x80开始,其余为0;X923填充则在最后一个字节记录填充数量,其余为0。文章通过Python示例展示了这些填充方法的使用。
摘要由CSDN通过智能技术生成


分组密码要求明文长度为分组大小的整数倍,如AES分组大小为16字节。若不满足该要求,则需要将最后一个明文分组进行填充。以下为几种主流填充方法。

pkcs7

PKCS7是几乎各个加密算法都遵循的填充算法,比如OpenSSL就使用它作为默认填充算法。

文档:RFC 2315: PKCS #7: Cryptographic Message Syntax Version 1.5 (rfc-editor.org)

比如AES(分组长度16字节)加密"Unaligned",该字符串长9字节,还需要7字节,于是在后面追加7字节0x07。

from Crypto.Util.Padding import pad, unpad
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from binascii import b2a_hex

data = b'Unaligned'   # 9 bytes
key = get_random_bytes(32)
iv = get_random_bytes(16)

cipher1 = AES.new(key, AES.MODE_CBC, iv)
pad_data = pad(data, 16)
print(b2a_hex(pad_data))
# b'556e616c69676e656407070707070707'
ct = cipher1.encrypt(pad_data)

cipher2 = AES.new(key, AES.MODE_CBC, iv)
pt = unpad(cipher2.decrypt(ct), 16)
print(b2a_hex(pt))
# b'556e616c69676e6564'

再举两个例子:

from Crypto.Util.Padding import pad, unpad
from binascii import b2a_hex

data = b'Unaligned0'

style = "pkcs7"
pad_data = pad(data, 16, style)
print(b2a_hex(pad_data))
# b'556e616c69676e656430060606060606'

print(b2a_hex(unpad(pad_data, 16)))
# b'556e616c69676e656430'

data = b'0123456789012345'
pad_data = pad(data, 16, style)
print(b2a_hex(pad_data))
# b'3031323334353637383930313233343510101010101010101010101010101010'

print(b2a_hex(unpad(pad_data, 16, style)))
# b'30313233343536373839303132333435'

可以看出,填充后的最后一个字节一定是填充量。

逆过程unpad则需要注意进行各种检查:

pdata_len = len(padded_data)
if pdata_len == 0:
        raise ValueError("Zero-length input cannot be unpadded")
if pdata_len % block_size:
        raise ValueError("Input data is not padded")

padding_len = bord(padded_data[-1])
if padding_len<1 or padding_len>min(block_size, pdata_len):
	raise ValueError("Padding is incorrect.")
return padded_data[:-padding_len]

还有一种填充方法叫做PKCS5,其实就是分组长度固定为8字节,而PKCS7的分组长度为1-255字节。

PKCS #5文档:RFC 2898: PKCS #5: Password-Based Cryptography Specification Version 2.0 (rfc-editor.org)

iso7816

填充值第一个字节为 0x80,其他字节填 0。

from Crypto.Util.Padding import pad, unpad
from binascii import b2a_hex

data = b'Unaligned'

style = "iso7816"
pad_data = pad(data, 16, style)
print(b2a_hex(pad_data))
# b'556e616c69676e656480000000000000'

print(b2a_hex(unpad(pad_data, 16, style)))
# b'556e616c69676e6564'

data = b'\x00\x01\x02\x03\x04\x05\x06\x07' \
       b'\x00\x01\x02\x03\x04\x05\x06\x80'
style = "iso7816"
pad_data = pad(data, 16, style)
print(b2a_hex(pad_data))
# b'0001020304050607000102030405068080000000000000000000000000000000'

print(b2a_hex(unpad(pad_data, 16, style)))
# b'00010203040506070001020304050680'

unpad:

pdata_len = len(padded_data)
if pdata_len == 0:
    raise ValueError("Zero-length input cannot be unpadded")
if pdata_len % block_size:
	raise ValueError("Input data is not padded")

padding_len = pdata_len - padded_data.rfind(bchr(128))
if padding_len<1 or padding_len>min(block_size, pdata_len):
    raise ValueError("Padding is incorrect.")
if padding_len>1 and padded_data[1-padding_len:]!=bchr(0)*(padding_len-1):
	raise ValueError("ISO 7816-4 padding is incorrect.")
return padded_data[:-padding_len]

x923

填充值最后一个字节为填充的数量数,其他字节填 0。

from Crypto.Util.Padding import pad, unpad
from binascii import b2a_hex

data = b'Unaligned'

style = "x923"
pad_data = pad(data, 16, style)
print(b2a_hex(pad_data))
# b'556e616c69676e656400000000000007'

print(b2a_hex(unpad(pad_data, 16, style)))
# b'556e616c69676e6564'


data = b'0123456789012345'

pad_data = pad(data, 16, style)
print(b2a_hex(pad_data))
# b'3031323334353637383930313233343500000000000000000000000000000010'

print(b2a_hex(unpad(pad_data, 16, style)))
# b'30313233343536373839303132333435'

unpad:

pdata_len = len(padded_data)
if pdata_len == 0:
    raise ValueError("Zero-length input cannot be unpadded")
if pdata_len % block_size:
	raise ValueError("Input data is not padded")


padding_len = bord(padded_data[-1])
if padding_len<1 or padding_len>min(block_size, pdata_len):
    raise ValueError("Padding is incorrect.")
if padded_data[-padding_len:-1]!=bchr(0)*(padding_len-1):
	raise ValueError("ANSI X.923 padding is incorrect.")
return padded_data[:-padding_len]

其它填充方式

ISO10126,填充值最后一个字节为填充的字节数,其他字节随机处理。

zero-padding,填充值全0。

TBC(Trailing-Bit-Compliment),明文最后一位为1时填充 0x00,最后一位为0时填充“0xFF”。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值