fix(security): K-5 – LDAP/CalDAV/SMTP-Verschlüsselung auf zentralen Datenschlüssel
ldap_service/caldav_service/email_service hatten je eine eigene _fernet()/ _decrypt_password(), die am JWT-SECRET_KEY hing. Damit honorierten sie das in core/crypto bereits umgesetzte SECRET_KEY_DATA NICHT – eine JWT-Key-Kompromittierung hätte weiterhin LDAP-/CalDAV-/SMTP-Passwörter offengelegt. Jetzt delegieren alle drei an core.crypto.get_fernet_key()/decrypt_value. Da auf beiden Servern SECRET_KEY_DATA nicht gesetzt ist, ist die Ableitung heute identisch (sha256(SECRET_KEY)) → bestehende verschlüsselte Werte bleiben lesbar, kein Bruch. Sobald SECRET_KEY_DATA gesetzt wird, gilt die Trennung dann konsistent für ALLE Datenverschlüsselung (TOTP + LDAP + CalDAV + SMTP). 190/190 Tests grün. Deployed 137 + 164. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -34,9 +34,10 @@ log = logging.getLogger(__name__)
|
|||||||
# ── Crypto (shared with SMTP/LDAP) ────────────────────────────────────────────
|
# ── Crypto (shared with SMTP/LDAP) ────────────────────────────────────────────
|
||||||
|
|
||||||
def _fernet():
|
def _fernet():
|
||||||
|
# K-5: zentraler Datenschlüssel (nutzt SECRET_KEY_DATA wenn gesetzt, sonst SECRET_KEY).
|
||||||
from cryptography.fernet import Fernet
|
from cryptography.fernet import Fernet
|
||||||
key = hashlib.sha256(settings.secret_key.encode()).digest()
|
from app.core.crypto import get_fernet_key
|
||||||
return Fernet(base64.urlsafe_b64encode(key))
|
return Fernet(get_fernet_key())
|
||||||
|
|
||||||
|
|
||||||
def encrypt_password(plain: str) -> str:
|
def encrypt_password(plain: str) -> str:
|
||||||
|
|||||||
@@ -44,13 +44,9 @@ def _html_wrapper(title: str, body: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _decrypt_password(encrypted: str) -> str:
|
def _decrypt_password(encrypted: str) -> str:
|
||||||
"""Fernet-Entschlüsselung (gleiche Implementierung wie ldap_service)."""
|
"""Fernet-Entschlüsselung über den zentralen Datenschlüssel (K-5)."""
|
||||||
import base64
|
from app.core.crypto import decrypt_value
|
||||||
import hashlib
|
return decrypt_value(encrypted)
|
||||||
from cryptography.fernet import Fernet
|
|
||||||
key = hashlib.sha256(settings.secret_key.encode()).digest()
|
|
||||||
f = Fernet(base64.urlsafe_b64encode(key))
|
|
||||||
return f.decrypt(encrypted.encode()).decode()
|
|
||||||
|
|
||||||
|
|
||||||
def _smtp_send_sync(cfg: SmtpConfig, to: str, subject: str, html: str) -> None:
|
def _smtp_send_sync(cfg: SmtpConfig, to: str, subject: str, html: str) -> None:
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def _fernet():
|
def _fernet():
|
||||||
|
# K-5: zentraler Datenschlüssel (nutzt SECRET_KEY_DATA wenn gesetzt, sonst SECRET_KEY).
|
||||||
from cryptography.fernet import Fernet
|
from cryptography.fernet import Fernet
|
||||||
key = hashlib.sha256(settings.secret_key.encode()).digest()
|
from app.core.crypto import get_fernet_key
|
||||||
return Fernet(base64.urlsafe_b64encode(key))
|
return Fernet(get_fernet_key())
|
||||||
|
|
||||||
|
|
||||||
def encrypt_password(plain: str) -> str:
|
def encrypt_password(plain: str) -> str:
|
||||||
|
|||||||
Reference in New Issue
Block a user