qecho / src /security.py
valent-p's picture
refactor: modularize application by extracting core logic into dedicated services, security, database, and router modules.
fa85d00
Raw History Blame Contribute Delete
1.45 kB
import hashlib
import base64
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
# --- CORE LOGIC: THE TWIN KEY GENERATOR ---
def generate_keys(group_name: str, password: str) -> tuple[str, str]:
"""
Generates two distinct values from the inputs:
1. encryption_key: Used to lock/unlock the data (Fernet).
2. blind_index: Used to find the data in the database.
Why separate them?
If the DB is hacked, they see the 'blind_index'.
They cannot reverse-engineer the 'encryption_key' from the index easily.
"""
# 1. Use the group_name as the Salt.
# This ensures "ProjectX" generates different keys than "ProjectY".
salt = group_name.encode()
# 2. Derive a 32-byte Master Key from the password
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
master_key_bytes = kdf.derive(password.encode())
# 3. Create the Fernet Key (Base64 encoded version of master key)
encryption_key = base64.urlsafe_b64encode(master_key_bytes)
# 4. Create the Blind Index (Hash of the master key)
# We hash the key again so the database admin sees a hash,
# but not the actual key used for decryption.
blind_index = hashlib.sha256(master_key_bytes).hexdigest()
return encryption_key, blind_index