33 lines
1.2 KiB
Python
33 lines
1.2 KiB
Python
"""
|
|
AES-256-GCM Verschluesselung fuer Secrets at rest (SSH-Private-Keys, TOTP-Secrets).
|
|
|
|
Prinzip (siehe Konzept 6.4): Der Key-Encryption-Key (KEK) liegt NICHT in der
|
|
Datenbank, sondern kommt aus app.config.settings (systemd-creds/Env). Jeder
|
|
verschluesselte Datensatz erhaelt einen frischen, zufaelligen Nonce; Nonce +
|
|
Ciphertext + Auth-Tag werden gemeinsam gespeichert.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
|
|
|
from app.config import settings
|
|
|
|
NONCE_LEN = 12 # 96 Bit, empfohlene GCM-Noncelaenge
|
|
|
|
|
|
def encrypt_secret(plaintext: bytes, *, associated_data: bytes = b"") -> bytes:
|
|
"""Verschluesselt plaintext mit dem globalen KEK. Rueckgabe: nonce || ciphertext."""
|
|
aesgcm = AESGCM(settings.kek)
|
|
nonce = os.urandom(NONCE_LEN)
|
|
ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data or None)
|
|
return nonce + ciphertext
|
|
|
|
|
|
def decrypt_secret(blob: bytes, *, associated_data: bytes = b"") -> bytes:
|
|
"""Entschluesselt einen mit encrypt_secret() erzeugten Blob."""
|
|
aesgcm = AESGCM(settings.kek)
|
|
nonce, ciphertext = blob[:NONCE_LEN], blob[NONCE_LEN:]
|
|
return aesgcm.decrypt(nonce, ciphertext, associated_data or None)
|