File size: 1,454 Bytes
fa85d00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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