aes数据填充问题-创新互联

问题

因为aes加解密对数据大小要求是16的倍数。但如果直接填充,等解密时不知道哪个字节是填充的,网上大多直接使用\x00填充尾部,然后把解密出来的数据直接使用s.rstrip()删除尾部的数据。
但如果原数据是以\x00结尾呢,则导致不能100%还原数据。
比如传输的程序不能运行了,大小不一样。。

成都创新互联长期为上千余家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为天镇企业提供专业的做网站、网站设计,天镇网站改版等技术服务。拥有10多年丰富建站经验和众多成功案例,为您定制开发。解决办法

设想,数据最后一位为标志位,用来储存填充位数。然后每当接受一组数据时,先获取标志位,然后就知道哪些位是填充的了,可以精准删除填充数据
假设原数据是’\x01\0x2’
这是2位数据,除去最后一位标志位,再填充13个\x00,最后一位使用\x0e填充(16进制,13为e)
最后填充的数据则是
'\x01\x02\x00\x00…\x0e’总共16位
下面是测试代码

a =b'\x01\x02\x03\x05'
    len2 =15-len(a)%16
    print("长度",len2)
    for i in range(len2):
        a+=b'\x00'
    a += len2.to_bytes(1,'big')  # 标志位,to_bytes是数字转为字节型
    print("a填充",len(a),a)
    #去除
    len1 = len(a)
    end = a[len1-1:len1] #获取标志位
    sum = int.from_bytes(end,'big') #填充的个数
    a = a[0:-(sum+1)]#切片,获取原数据
    print(a)

下面是编写的加解密代码

#默认使用cbc加密方式,可以对文件二进制流进行加解密

from Crypto.Cipher import AES
import base64
#

class Aescrypt():
    def __init__(self,key,model,iv):
        self.key = key
        self.model = model
        self.iv = iv

    def file_add16(self,par):#文件数据进行填充,在最后16位数据中,最后一位判断位,表示有几个是填充的
        len1 = 15 - (len(par) % 16)#计算填充的个数
        for i in range(len1):
            par +=b'\x00'
        par +=len1.to_bytes(1,'big')#标志位
        return par

    def aesencrypt_file(self,text):
        text = self.file_add16(text)

        self.aes = AES.new(self.key,self.model,self.iv)
        self.encrypt_text = self.aes.encrypt(text)
        return self.encrypt_text

    def aesdecrypt_file(self,text):#aes cbc解密
        self.aes = AES.new(self.key,self.model,self.iv)
        try:
            self.decrypt_text = self.aes.decrypt(text)
        except:
            print("数据不是16倍数",len(text),text)
        #清除填充数据
        data = self.decrypt_text
        len1 = len(data)
        end = data[len1-1:len1]#获取标志位
        sum = int.from_bytes(end, 'big')  # 填充的个数
        self.decrypt_text = data[0:-(sum + 1)]  # 切片,获取原数据
        return self.decrypt_text
def decode(data,passwd = b"1234567812345678",iv = b'0000000000000000'):
#对base64解密再aes解密
    data = base64.b64decode(data)
    aescryptor = Aescrypt(passwd, AES.MODE_CBC, iv)  # CBC模式
    out = aescryptor.aesdecrypt_file(data)

    return out
def encode(data,passwd = b"1234567812345678",iv = b'0000000000000000'):
    #对字节型数据加密成aes,再base64
    if type(data)==str:
        data= data.encode()
    aescryptor = Aescrypt(passwd, AES.MODE_CBC, iv)  # CBC模式
    out = aescryptor.aesencrypt_file(data)
    out = base64.b64encode(out)
    return out #bytes
# if __name__ == '__main__':
#     passwd = b"1234567812345678"
#     iv = b'1234567812345678'
#     aescryptor = Aescrypt(passwd,AES.MODE_CBC,iv) # CBC模式
#     text = b'sfdffd11111'
#     print(len(text))
#     en_text = aescryptor.aesencrypt(text)
#     print("密文:",en_text)
#
#     text = aescryptor.aesdecrypt(en_text)
#     print("明文:",text)

使用方法把上面文件保存为cdde.py
然后创建一个test.py

import cdde
#a='ok'
a=b'\x01\x02\x03'
a1= cdde.encode(a)
print(a1)
a2 = cdde.decode(a1)
print(a2)

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


当前文章:aes数据填充问题-创新互联
本文网址:http://hbruida.cn/article/dccshs.html