实现Rijndael算法后加密输出文件异常增大的原因排查
问题原因分析
核心问题:文件写入的错误用法
加密后文件体积暴增的直接原因是写入文件时误用了bytes(val):
- 在Python中,
bytes(n)(n为整数)的作用是创建包含n个空字节(\x00)的字节串,而非将整数n转换为对应的单个字节。 - 例如当
val=255时,bytes(255)会生成255个字节,而非预期的b'\xff'。这直接导致每个加密后的字节被扩展成对应数值长度的字节串,最终文件体积疯狂膨胀。
其他潜在隐患
代码里还有几个可能引发异常或逻辑错误的问题:
- 数组类型混乱:
- 原始文件读取为
np.uint8,但padding用np.zeros默认生成float64类型数组,np.append后整个数组类型变为float64,后续转int虽暂时没问题,但容易引发数值偏差。 bin_to_hex_arr返回np.int8类型的密钥数组,和uint8的文件数组做XOR运算后,数组类型会被提升为int,可能出现负数(int8范围是-128~127),后续处理会产生异常。
- 原始文件读取为
- Rijndael算法实现不完整:
你只实现了S盒替换,缺少Rijndael必需的行移位、列混合、轮密钥扩展等核心步骤,这不是一个具备安全性的完整AES加密实现。
修复方案
修正文件写入逻辑:
将写入代码的save.write(bytes(val))改为save.write(bytes([val])),这样会把整数val转换为对应的单个字节写入文件。统一数组类型:
- padding时指定类型为
uint8:padding = np.zeros(16 - (len(file) % 16), dtype=np.uint8) bin_to_hex_arr返回uint8类型,避免负数:return hexa.reshape([4, 4]).astype(np.uint8)- 同时给十六进制密钥补全前导零,确保长度符合128位密钥要求:
hexa = hex(num).replace("0x", "").zfill(32)
- padding时指定类型为
补全Rijndael算法步骤:
如果要实现标准AES加密,必须添加轮密钥扩展、行移位、列混合、轮密钥加等步骤,否则加密结果不具备安全性。
修复后的关键代码片段
# 修正padding类型 padding = np.zeros(16 - (len(file) % 16), dtype=np.uint8) file = np.append(file, padding) file = file.reshape([num_boxes, 4, 4]) # 修正密钥转换函数 def bin_to_hex_arr(num): hexa = hex(num).replace("0x", "").zfill(32) hexa = [int(hexa[i:i+2], 16) for i in range(0, len(hexa), 2)] hexa = np.array(hexa) return hexa.reshape([4, 4]).astype(np.uint8) # 修正文件写入逻辑 save = open(f"{FILE_TO_ENCRYPT}.encrypt", "wb") for val in file.ravel(): save.write(bytes([val])) save.close()
内容的提问来源于stack exchange,提问作者RubidiumCode
相关产品推荐
相关产品推荐

