bifroest/app/core/crypto.py
2026-10-27 08:34:17 +01:00

40 lines
1.5 KiB
Python

"""Verschlüsselung von Geheimnissen in der Datenbank (→ Konzept 6.2).
Master-Key aus AIW_SECRET_KEY (Fernet, base64). Mehrere Keys kommagetrennt:
der erste verschlüsselt, alle entschlüsseln. So lässt sich der Key wechseln,
ohne alte Einträge sofort neu zu verschlüsseln.
"""
from cryptography.fernet import Fernet, InvalidToken, MultiFernet
from app.core.errors import Invalid
def generate_key() -> str:
return Fernet.generate_key().decode()
class Vault:
def __init__(self, keys: str):
parts = [k.strip() for k in keys.split(",") if k.strip()]
try:
self.fernet = MultiFernet([Fernet(k) for k in parts]) if parts else None
except ValueError as e:
raise RuntimeError("AIW_SECRET_KEY ist kein gültiger Fernet-Key (aiw gen-key).") from e
@property
def ready(self) -> bool:
return self.fernet is not None
def encrypt(self, value: str) -> str:
if self.fernet is None:
raise Invalid("Geheimnisse können nicht gespeichert werden: AIW_SECRET_KEY ist nicht gesetzt.")
return self.fernet.encrypt(value.encode()).decode()
def decrypt(self, token: str) -> str:
if self.fernet is None:
raise RuntimeError("AIW_SECRET_KEY ist nicht gesetzt.")
try:
return self.fernet.decrypt(token.encode()).decode()
except InvalidToken as e:
raise RuntimeError("Geheimnis lässt sich nicht entschlüsseln (falscher AIW_SECRET_KEY?).") from e