fix(security): K-5 – LDAP/CalDAV/SMTP-Verschlüsselung auf zentralen Datenschlüssel
Security Audit / Node.js Dependency Audit (push) Has been cancelled
Security Audit / Python Dependency Audit (push) Has been cancelled

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:
2026-06-23 13:56:01 +02:00
co-authored by Claude Opus 4.8
parent e1d423e634
commit 31e39c6bd9
3 changed files with 9 additions and 11 deletions
+3 -2
View File
@@ -34,9 +34,10 @@ log = logging.getLogger(__name__)
# ── Crypto (shared with SMTP/LDAP) ────────────────────────────────────────────
def _fernet():
# K-5: zentraler Datenschlüssel (nutzt SECRET_KEY_DATA wenn gesetzt, sonst SECRET_KEY).
from cryptography.fernet import Fernet
key = hashlib.sha256(settings.secret_key.encode()).digest()
return Fernet(base64.urlsafe_b64encode(key))
from app.core.crypto import get_fernet_key
return Fernet(get_fernet_key())
def encrypt_password(plain: str) -> str:
+3 -7
View File
@@ -44,13 +44,9 @@ def _html_wrapper(title: str, body: str) -> str:
def _decrypt_password(encrypted: str) -> str:
"""Fernet-Entschlüsselung (gleiche Implementierung wie ldap_service)."""
import base64
import hashlib
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()
"""Fernet-Entschlüsselung über den zentralen Datenschlüssel (K-5)."""
from app.core.crypto import decrypt_value
return decrypt_value(encrypted)
def _smtp_send_sync(cfg: SmtpConfig, to: str, subject: str, html: str) -> None:
+3 -2
View File
@@ -23,9 +23,10 @@ logger = logging.getLogger(__name__)
def _fernet():
# K-5: zentraler Datenschlüssel (nutzt SECRET_KEY_DATA wenn gesetzt, sonst SECRET_KEY).
from cryptography.fernet import Fernet
key = hashlib.sha256(settings.secret_key.encode()).digest()
return Fernet(base64.urlsafe_b64encode(key))
from app.core.crypto import get_fernet_key
return Fernet(get_fernet_key())
def encrypt_password(plain: str) -> str: