feature/integracion-cpanel-asrecovery
This commit is contained in:
@@ -1,59 +1,68 @@
|
||||
"""Utilidades de cifrado para passwords usando DPAPI en Windows."""
|
||||
"""Utilidades de cifrado para passwords (DPAPI en Windows, Fernet en Linux)."""
|
||||
|
||||
import base64
|
||||
import win32crypt
|
||||
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 usando DPAPI de Windows.
|
||||
|
||||
Args:
|
||||
password: Contraseña en texto plano
|
||||
|
||||
Returns:
|
||||
Contraseña cifrada en base64
|
||||
"""
|
||||
"""Cifra una contraseña."""
|
||||
if not password:
|
||||
return ""
|
||||
|
||||
|
||||
try:
|
||||
encrypted_bytes = win32crypt.CryptProtectData(
|
||||
password.encode('utf-8'),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
0
|
||||
)
|
||||
return base64.b64encode(encrypted_bytes).decode('ascii')
|
||||
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}")
|
||||
raise RuntimeError(f"Error cifrando contraseña: {e}") from e
|
||||
|
||||
|
||||
def decrypt_password(encrypted_password: str) -> str:
|
||||
"""
|
||||
Descifra una contraseña usando DPAPI de Windows.
|
||||
|
||||
Args:
|
||||
encrypted_password: Contraseña cifrada en base64
|
||||
|
||||
Returns:
|
||||
Contraseña en texto plano
|
||||
"""
|
||||
"""Descifra una contraseña."""
|
||||
if not encrypted_password:
|
||||
return ""
|
||||
|
||||
|
||||
try:
|
||||
encrypted_bytes = base64.b64decode(encrypted_password)
|
||||
decrypted_bytes = win32crypt.CryptUnprotectData(
|
||||
encrypted_bytes,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
0
|
||||
)[1]
|
||||
return decrypted_bytes.decode('utf-8')
|
||||
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}")
|
||||
raise RuntimeError(f"Error descifrando contraseña: {e}") from e
|
||||
|
||||
Reference in New Issue
Block a user