Files
CloudRecoveryAS/app/utils/crypto.py

69 lines
1.9 KiB
Python

"""Utilidades de cifrado para passwords (DPAPI en Windows, Fernet en Linux)."""
import base64
import sys
from pathlib import Path
from typing import Optional
from ..constants import DATA_DIR
_IS_WINDOWS = sys.platform == "win32"
_SECRET_FILE = DATA_DIR / ".secret"
def _get_fernet():
from cryptography.fernet import Fernet
DATA_DIR.mkdir(parents=True, exist_ok=True)
if not _SECRET_FILE.exists():
key = Fernet.generate_key()
_SECRET_FILE.write_bytes(key)
try:
_SECRET_FILE.chmod(0o600)
except OSError:
pass
else:
key = _SECRET_FILE.read_bytes()
return Fernet(key)
def encrypt_password(password: str) -> str:
"""Cifra una contraseña."""
if not password:
return ""
try:
if _IS_WINDOWS:
import win32crypt
encrypted_bytes = win32crypt.CryptProtectData(
password.encode("utf-8"), None, None, None, None, 0
)
return base64.b64encode(encrypted_bytes).decode("ascii")
fernet = _get_fernet()
return fernet.encrypt(password.encode("utf-8")).decode("ascii")
except Exception as e:
raise RuntimeError(f"Error cifrando contraseña: {e}") from e
def decrypt_password(encrypted_password: str) -> str:
"""Descifra una contraseña."""
if not encrypted_password:
return ""
try:
if _IS_WINDOWS:
import win32crypt
encrypted_bytes = base64.b64decode(encrypted_password)
decrypted_bytes = win32crypt.CryptUnprotectData(
encrypted_bytes, None, None, None, 0
)[1]
return decrypted_bytes.decode("utf-8")
fernet = _get_fernet()
return fernet.decrypt(encrypted_password.encode("ascii")).decode("utf-8")
except Exception as e:
raise RuntimeError(f"Error descifrando contraseña: {e}") from e