"""Nexus — Encryption Utilities (Fernet) Shared crypto module — used by SSH pool, DB credentials, password presets. """ import logging from cryptography.fernet import Fernet from server.config import settings logger = logging.getLogger("nexus.crypto") def _fernet() -> Fernet: """Create Fernet instance from ENCRYPTION_KEY. ENCRYPTION_KEY is mandatory — main.py validates it at startup. No silent fallback: if ENCRYPTION_KEY is empty, that's a configuration error that must be surfaced, not masked. """ key = settings.ENCRYPTION_KEY if not key: raise RuntimeError( "ENCRYPTION_KEY is empty — cannot initialize Fernet encryption. " "Set NEXUS_ENCRYPTION_KEY in .env (generated by install wizard)." ) return Fernet(key.encode() if isinstance(key, str) else key) _fernet_instance: Fernet | None = None def get_fernet() -> Fernet: global _fernet_instance if _fernet_instance is None: _fernet_instance = _fernet() return _fernet_instance def encrypt_value(plaintext: str) -> str: """Encrypt a string using Fernet""" if not plaintext: return plaintext return get_fernet().encrypt(plaintext.encode()).decode() def decrypt_value(ciphertext: str) -> str: """Decrypt a Fernet-encrypted string""" if not ciphertext: return ciphertext try: return get_fernet().decrypt(ciphertext.encode()).decode() except Exception as e: logger.warning(f"Fernet decryption failed (key mismatch?): {e}") raise ValueError("凭据解密失败") from e