使用的包:
pycryptodome
安装 pip install pycryptodome
导入 :
from Crypto.Cipher import AES
import base64
import random
import secrets
基本参数
mode = 2 # mode 1:ECB,2:CBC
KEYLENGTH = 32 # 密钥长度:256bit(32bytes)
BS = 16 # 可加密的固定长度
# 当长度不足16时,用于填充信息的,如果为a,则用16进制的16-a 填充
# 如果长度正好为16,则在后面填充16位的 16进度16,解密时最后16bytes解密出来是空
# s为bytes类型
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS).encode()
# 解密时把填充的信息去掉
unpad = lambda s: s[0:-s[-1]]
加密文件:
# 加密前可以将文件压缩,以减小加密运算量
def aes_encrypt_file(filepath, encrypted_file_path):
'''使用256位加密,密钥长度256bit,iv固定16bytes'''
key = random.randbytes(KEYLENGTH) # 随机生成密钥和偏移量
iv = random.randbytes(BS)
# 上面的随机数生成器,不能用于产生密钥,应该使用secrets.token_bytes(n)来产生
aes = AES.new(key, mode, iv=iv) # 生成AES对象
filesize = os.path.getsize(filepath) # 要加密的文件大小
filllength = filesize % BS
times = filesize // BS # 计算读取次数,取商,剩余量作为最后一次读取并填充到16bytes
with open(zipfilepath, 'rb') as rfs:
with open(encrypted_file_path, 'wb') as wfs:
for time in range(times): # 循环读取并加密、写入到新文件
data = rfs.read(BS)
data_en = aes.encrypt(data)
wfs.write(data_en)
data = rfs.read(BS) # 最后一次读取
data = pad(data) # 填充
data_en = aes.encrypt(data) # 加密
wfs.write(data_en)
return key, iv # 返回 key和iv,用于后期解密
解密文件:
由于是对称加密,key和iv使用加密时的key和iv
def aesdefile(encrypted_file_path, decrypted_file_path, key, iv):
aes = AES.new(key, mode, iv=iv) # 生成AES对象
filesize = os.path.getsize(encrypted_file_path) # 获取 文件大小
times = filesize // BS - 1 #计算读取次数,由于被填充过,所以可以整除,只有最后一次需要去除填充
with open(encrypted_file_path, 'rb') as rfs:
with open(decrypted_file_path, 'wb') as wfs:
for time in range(times): # 循环读取文件
data = rfs.read(BS)
data_en = aes.decrypt(data)
wfs.write(data_en)
data = rfs.read(BS) # 最后一次读取,
data_en = unpad(aes.decrypt(data)) # 解密并去除填充的内容,
wfs.write(data_en)
os.remove(encrypted_file_path) # 删除 未解密的文件