Python PyCrypto encripta / desencripta archivos de texto con AES

Ya tengo un progtwig que funciona, pero lo único que no funciona es la función decrypt_file() que tengo. Todavía puedo copiar el texto cifrado del archivo y ponerlo en mi función decrypt() y hacer que funcione, pero cuando bash usar mi función decrypt_file() , que se supone que será útil, arroja un error. Ahora sé que el 99,999% estoy seguro de que mis funciones encrypt() y decrypt() están bien, pero hay algo con la conversión de bytes y cadenas cuando leo y codifico el archivo de texto que produce un error; Simplemente no puedo encontrar el hangup. ¡Por favor ayuda!

Mi progtwig:

 from Crypto import Random from Crypto.Cipher import AES def encrypt(message, key=None, key_size=256): def pad(s): x = AES.block_size - len(s) % AES.block_size return s + ((bytes([x])) * x) padded_message = pad(message) if key is None: key = Random.new().read(key_size // 8) iv = Random.new().read(AES.block_size) cipher = AES.new(key, AES.MODE_CBC, iv) return iv + cipher.encrypt(padded_message) def decrypt(ciphertext, key): unpad = lambda s: s[:-s[-1]] iv = ciphertext[:AES.block_size] cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = unpad(cipher.decrypt(ciphertext))[AES.block_size:] return plaintext def encrypt_file(file_name, key): f = open(file_name, 'r') plaintext = f.read() plaintext = plaintext.encode('utf-8') enc = encrypt(plaintext, key) f.close() f = open(file_name, 'w') f.write(str(enc)) f.close() def decrypt_file(file_name, key): def pad(s): x = AES.block_size - len(s) % AES.block_size return s + ((str(bytes([x]))) * x) f = open(file_name, 'r') plaintext = f.read() x = AES.block_size - len(plaintext) % AES.block_size plaintext += ((bytes([x]))) * x dec = decrypt(plaintext, key) f.close() f = open(file_name, 'w') f.write(str(dec)) f.close() key = b'\xbf\xc0\x85)\x10nc\x94\x02)j\xdf\xcb\xc4\x94\x9d(\x9e[EX\xc8\xd5\xbfI{\xa2$\x05(\xd5\x18' encrypt_file('to_enc.txt', key) 

El archivo de texto encripté:

 b';c\xb0\xe6Wv5!\xa3\xdd\xf0\xb1\xfd2\x90B\x10\xdf\x00\x82\x83\x9d\xbc2\x91\xa7i M\x13\xdc\xa7' 

Mi error al intentar decrypt_file :

  Traceback (most recent call last): File "C:\Python33\testing\test\crypto.py", line 56, in  decrypt_file('to_enc.txt', key) File "C:\Python33\testing\test\crypto.py", line 45, in decrypt_file plaintext += ((bytes([x]))) * x TypeError: Can't convert 'bytes' object to str implicitly [Finished in 1.5s] 

Cuando reemplazo la línea 45 con: plaintext += ((str(bytes([x])))) * x , este es el error que obtengo:

 Traceback (most recent call last): File "C:\Python33\testing\test\crypto.py", line 56, in  decrypt_file('to_enc.txt', key) File "C:\Python33\testing\test\crypto.py", line 46, in decrypt_file dec = decrypt(plaintext, key) File "C:\Python33\testing\test\crypto.py", line 23, in decrypt plaintext = unpad(cipher.decrypt(ciphertext))[AES.block_size:] File "C:\Python33\lib\site-packages\Crypto\Cipher\blockalgo.py", line 295, in decrypt return self._cipher.decrypt(ciphertext) ValueError: Input strings must be a multiple of 16 in length [Finished in 1.4s with exit code 1] 

Eché un vistazo más de cerca a su código, y vi que había varios problemas con él. El primero es que el criptográfico funciona con bytes, no con texto. Así que es mejor mantener los datos como una cadena de bytes. Esto se hace simplemente colocando un carácter ‘b’ en el modo. De esta manera, puede deshacerse de toda la encoding y la conversión de bytes que estaba tratando de hacer.

Reescribí todo el código también utilizando modismos de Python más nuevos. Aquí está.

 #!/usr/bin/python3 from Crypto import Random from Crypto.Cipher import AES def pad(s): return s + b"\0" * (AES.block_size - len(s) % AES.block_size) def encrypt(message, key, key_size=256): message = pad(message) iv = Random.new().read(AES.block_size) cipher = AES.new(key, AES.MODE_CBC, iv) return iv + cipher.encrypt(message) def decrypt(ciphertext, key): iv = ciphertext[:AES.block_size] cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = cipher.decrypt(ciphertext[AES.block_size:]) return plaintext.rstrip(b"\0") def encrypt_file(file_name, key): with open(file_name, 'rb') as fo: plaintext = fo.read() enc = encrypt(plaintext, key) with open(file_name + ".enc", 'wb') as fo: fo.write(enc) def decrypt_file(file_name, key): with open(file_name, 'rb') as fo: ciphertext = fo.read() dec = decrypt(ciphertext, key) with open(file_name[:-4], 'wb') as fo: fo.write(dec) key = b'\xbf\xc0\x85)\x10nc\x94\x02)j\xdf\xcb\xc4\x94\x9d(\x9e[EX\xc8\xd5\xbfI{\xa2$\x05(\xd5\x18' encrypt_file('to_enc.txt', key) #decrypt_file('to_enc.txt.enc', key) 

En Python 3 (que está usando claramente) el modo predeterminado para los archivos que abre es texto, no binario. Cuando lee el archivo, obtiene cadenas en lugar de matrices de bytes. Eso no está de acuerdo con el cifrado.

En su código, debe reemplazar:

 open(file_name, 'r') 

con:

 open(file_name, 'rb') 

Lo mismo para cuando abres el archivo para escribir. En ese momento, puede deshacerse de todas las diversas ocurrencias en las que convierte de cadena a binario y viceversa.

Por ejemplo, esto puede desaparecer:

 plaintext = plaintext.encode('utf-8')