57 lines
1.6 KiB
Python
57 lines
1.6 KiB
Python
import base64
|
|
import os
|
|
import secrets
|
|
import string
|
|
from typing import Tuple
|
|
|
|
from cryptography.fernet import Fernet
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|
|
|
from app.core.config import settings
|
|
|
|
|
|
def generate_random_key(length: int = 16) -> str:
|
|
"""Generate a random access key."""
|
|
alphabet = string.ascii_letters + string.digits
|
|
return ''.join(secrets.choice(alphabet) for _ in range(length))
|
|
|
|
|
|
def derive_key(password: str, salt: bytes = None) -> Tuple[bytes, bytes]:
|
|
"""Derive a key from a password and salt using PBKDF2."""
|
|
if salt is None:
|
|
salt = os.urandom(16)
|
|
|
|
kdf = PBKDF2HMAC(
|
|
algorithm=hashes.SHA256(),
|
|
length=32,
|
|
salt=salt,
|
|
iterations=100000,
|
|
)
|
|
|
|
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
|
|
return key, salt
|
|
|
|
|
|
def encrypt_content(content: str, password: str = None) -> Tuple[str, bytes]:
|
|
"""Encrypt the content using Fernet symmetric encryption."""
|
|
if password is None:
|
|
password = settings.SECRET_KEY
|
|
|
|
key, salt = derive_key(password)
|
|
cipher = Fernet(key)
|
|
encrypted_data = cipher.encrypt(content.encode())
|
|
|
|
return encrypted_data.decode(), salt
|
|
|
|
|
|
def decrypt_content(encrypted_content: str, salt: bytes, password: str = None) -> str:
|
|
"""Decrypt the content using Fernet symmetric encryption."""
|
|
if password is None:
|
|
password = settings.SECRET_KEY
|
|
|
|
key, _ = derive_key(password, salt)
|
|
cipher = Fernet(key)
|
|
decrypted_data = cipher.decrypt(encrypted_content.encode())
|
|
|
|
return decrypted_data.decode() |