Ваши операции шифрования и дешифрования не являются зеркальным отображением друг друга.
def encrypt( self, s ):
iv = Random.new().read( AES.block_size ) # new IV
cipher = AES.new( self.key, AES.MODE_CBC, iv ) # create cipher
payload = s.encode("utf-8") # string to bytes
encrypted = cipher.encrypt(pad(payload)) # pad before encrypt
return base64.b64encode( iv + encrypted ) # b64 data
def decrypt( self, enc ):
data = base64.b64decode( enc ) # b64 data
iv = data[:AES.block_size] # split it up
encrypted = data[AES.block_size:] #
cipher = AES.new(self.key, AES.MODE_CBC, iv ) # recreate cipher
payload = unpad(cipher.decrypt( encrypted )) # unpad after decrypt
return payload.decode("utf8") # bytes to string
Только зашифрованные байты могут быть зашифрованы.Строки не являются байтами, поэтому сначала необходимо кодировать строки в байтовое представление.UTF-8 является подходящим представлением, но это может быть UTF-16 или даже UTF-32 ( читайте о различиях ).
Однако, поскольку шифр может обработать любой байт, я бы удалил часть, которая в настоящее время ограничивает эти функции строками.Я бы изменил их, чтобы они ожидали и возвращали байты, а затем либо:
- вызываем их как
x = aes.encrypt(s.encode('utf8'))
и s = aes.decrypt(x).decode('utf8')
соответственно, либо - делают функции-оболочки для обработки строк.
Для шифрования файлов вы можете напрямую сделать это:
with open('some.txt', 'rb') as fp:
encrypted = aes.encrypt(fp.read())
, и это вообще не будет навязывать какие-либо предположения о кодировке, но зашифровывает байты файла как они есть..
AES - блочный шифр, что означает, что encrypt(a) + encrypt(b)
совпадает с encrypt(a + b)
.Для шифрования файлов это очень полезно, потому что вы можете читать файл постепенно, кусками из N * AES.block_size
, только с добавленным последним блоком.Это намного эффективнее, чем чтение всего файла в память.Ваша текущая настройка encrypt
и decrypt
не использует это.