|
|
|
|
import os, random, struct
|
|
|
|
|
from Crypto.Cipher import AES
|
|
|
|
|
|
|
|
|
|
def encrypt_file(key, in_filename, out_filename=None, chunksize=64*1024):
|
|
|
|
|
""" Шифрует файл используя AES (режим CBC) с
|
|
|
|
|
заданным ключом.
|
|
|
|
|
|
|
|
|
|
key:
|
|
|
|
|
Ключ шифрования - строка длиной
|
|
|
|
|
16, 24 или 32 байта. Более длинные ключи
|
|
|
|
|
более безопасны.
|
|
|
|
|
|
|
|
|
|
in_filename:
|
|
|
|
|
Имя входного файла
|
|
|
|
|
|
|
|
|
|
out_filename:
|
|
|
|
|
Если None, будет использоваться «<in_filename> .enc».
|
|
|
|
|
|
|
|
|
|
chunksize:
|
|
|
|
|
Устанавливает размер фрагмента, который функция
|
|
|
|
|
использует для чтения и шифрования файла.Большие
|
|
|
|
|
размеры могут быть быстрее для некоторых файлов и машин.
|
|
|
|
|
кусок (chunk) должен делиться на 16.
|
|
|
|
|
"""
|
|
|
|
|
if not out_filename:
|
|
|
|
|
out_filename = in_filename + '.enc'
|
|
|
|
|
iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
|
|
|
|
|
iv = iv.encode('utf8')[0:16]
|
|
|
|
|
encryptor = AES.new(key, AES.MODE_CBC, iv)
|
|
|
|
|
filesize = os.path.getsize(in_filename)
|
|
|
|
|
with open(in_filename, 'rb') as infile:
|
|
|
|
|
with open(out_filename, 'wb') as outfile:
|
|
|
|
|
outfile.write(struct.pack('<Q', filesize))
|
|
|
|
|
outfile.write(iv)
|
|
|
|
|
while True:
|
|
|
|
|
chunk = infile.read(chunksize)
|
|
|
|
|
if len(chunk) == 0:
|
|
|
|
|
break
|
|
|
|
|
elif len(chunk) % 16 != 0:
|
|
|
|
|
chunk += b' ' * (16 - len(chunk) % 16)
|
|
|
|
|
outfile.write(encryptor.encrypt(chunk))
|
|
|
|
|
|
|
|
|
|
def decrypt_file(key, in_filename, out_filename=None, chunksize=24*1024):
|
|
|
|
|
""" Расшифровывает файл, используя AES (режим CBC) с
|
|
|
|
|
заданным ключом. Параметры аналогичны encrypt_file,
|
|
|
|
|
с одним отличием: out_filename, если не указано
|
|
|
|
|
будет in_filename без его последнего расширения
|
|
|
|
|
(т.е. если in_filename будет 'aaa.zip.enc', тогда
|
|
|
|
|
out_filename будет 'aaa.zip')
|
|
|
|
|
"""
|
|
|
|
|
if not out_filename:
|
|
|
|
|
out_filename = os.path.splitext(in_filename)[0]
|
|
|
|
|
with open(in_filename, 'rb') as infile:
|
|
|
|
|
origsize = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
|
|
|
|
|
iv = infile.read(16)
|
|
|
|
|
decryptor = AES.new(key, AES.MODE_CBC, iv)
|
|
|
|
|
with open(out_filename, 'wb') as outfile:
|
|
|
|
|
while True:
|
|
|
|
|
chunk = infile.read(chunksize)
|
|
|
|
|
if len(chunk) == 0:
|
|
|
|
|
break
|
|
|
|
|
outfile.write(decryptor.decrypt(chunk))
|
|
|
|
|
outfile.truncate(origsize)
|
|
|
|
|
def decrypt_file_bytes(key, in_filename, chunksize=24*1024):
|
|
|
|
|
""" Расшифровывает файл, используя AES (режим CBC) с
|
|
|
|
|
заданным ключом.
|
|
|
|
|
"""
|
|
|
|
|
lResult = b''
|
|
|
|
|
with open(in_filename, 'rb') as infile:
|
|
|
|
|
origsize = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
|
|
|
|
|
iv = infile.read(16)
|
|
|
|
|
decryptor = AES.new(key, AES.MODE_CBC, iv)
|
|
|
|
|
while True:
|
|
|
|
|
chunk = infile.read(chunksize)
|
|
|
|
|
if len(chunk) == 0:
|
|
|
|
|
break
|
|
|
|
|
lResult = lResult+decryptor.decrypt(chunk)
|
|
|
|
|
lResult=lResult[0:origsize]
|
|
|
|
|
return lResult
|