Hoy vamos a aprender cómo podemos almacenar un fichero cifrado y cómo descifrarlo para devolverlo en un response.

Vamos a utilizar la librería Fernet.
pip install cryptography
Primero vamos a crear una clave de cifrado con Fernet
def generate_key():
key = Fernet.generate_key()
return key.decode('utf-8')
Con esta función podemos obtener una clave aleatoria para Fernet, debemos almacenarla bien ya que se usará para descifrar los ficheros cifrados.
Ahora con estas funciones podremos cifrar y descifrar nuestros ficheros, se almacenarán con .enc
from cryptography.fernet import Fernet
import os
from dotenv import load_dotenv
load_dotenv()
FERNET_KEY = bytes(os.getenv("FERNET_KEY"), "utf-8")
fernet = Fernet(FERNET_KEY)
def generate_key():
key = Fernet.generate_key()
return key.decode('utf-8')
def cipher_file(original_file: bytes, save_path: str):
new_file_name = save_path + ".enc"
encrypted_data = fernet.encrypt(original_file)
with open(new_file_name, "wb") as encrypted_file:
encrypted_file.write(encrypted_data)
def decipher_file(encrypted_file_path: str):
# Leer el contenido cifrado desde el archivo
with open(encrypted_file_path, "rb") as encrypted_file:
encrypted_data = encrypted_file.read()
# Descifrar el contenido
decrypted_data = fernet.decrypt(encrypted_data)
# Devolver los datos descifrados directamente
return decrypted_data
def decipher_file_in_path(encrypted_file_path: str):
with open(encrypted_file_path, "rb") as encrypted_file:
encrypted_data = encrypted_file.read()
decrypted_data = fernet.decrypt(encrypted_data)
return decrypted_data
Con la función cipher_file cifrará el fichero que pasamos por bytes y lo almacenará en la ruta indicada con .enc al final.
Para pasar los ficheros por bytes usamos esta función:
@api.post("/add_file", status_code=status.HTTP_201_CREATED)
def add_file( pdf_file: UploadFile = File(...)):
upload_folder = "pdf"
# Obtener fecha actual
now = datetime.now()
dt_string = now.strftime("%d_%m_%Y_%H_%M_%S")
file_name = dt_string + ".pdf"
file_route = os.path.join(upload_folder, file_name)
cipher_file(pdf_file.file.read(), file_route)
return {"filename": file_name}
Se suben ficheros de tipo File(…) y se almacenan cifrados
Para obtener el fichero cifrado, usamos el método decipher_file y devolverá el fichero descifrado en forma de bytes. Para poder devolver este fichero de forma de File tenemos que hacer lo siguiente:
@api.get("/get_file/{path}", status_code=status.HTTP_200_OK)
def get_file(path: str):
# Verificar si el archivo existe
if not os.path.exists(path):
return {"error": "El archivo no existe"}
# Obtengo decrypted_data de fernet.decrypt
decrypted_data = decipher_file(ruta_fichero)
#print("decrypted_data" + str(decrypted_data))
# Devolver el fichero descifrado decrypted data tipo pdf (no tiene ruta)
return StreamingResponse(io.BytesIO(decrypted_data), media_type="application/pdf", headers={"Content-Disposition": f"attachment; filename={"file"}"})
De esta forma devolverlos el archivo descifrado.
Y finalmente, si queremos descifrar el archivo dentro del propio directorio usaremos la función decipher_file_in_path, directamente sobreescribe el archivo dentro del directorio.

Ingeniero en Informática, Investigador, me encanta crear cosas o arreglarlas y darles una nueva vida. Escritor y poeta. Más de 20 APPs publicadas y un libro en Amazon.