File size: 2,433 Bytes
7a317d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from cryptography.fernet import Fernet
import os
import sys
import logging
from typing import Optional

# -------------------------------------------------------------------------
# ENCRYPTION CONFIGURATION - PRODUCTION READY
# -------------------------------------------------------------------------

# Environment detection
ENVIRONMENT = os.getenv("ENVIRONMENT", "development")
IS_PRODUCTION = ENVIRONMENT == "production"

# Encryption Key - Load from environment variable
ENCRYPTION_KEY = os.getenv("ENCRYPTION_KEY")

if not ENCRYPTION_KEY:
    if IS_PRODUCTION:
        logging.critical("🔴 FATAL ERROR: ENCRYPTION_KEY must be set in production environment")
        logging.critical("Generate one with: python -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())'")
        sys.exit(1)  # Fail-fast in production
    else:
        # Development fallback with ephemeral key
        ENCRYPTION_KEY = Fernet.generate_key().decode()
        logging.warning("⚠️  WARNING: Using ephemeral encryption key (development only)")

# Initialize cipher
cipher_suite = Fernet(ENCRYPTION_KEY.encode() if isinstance(ENCRYPTION_KEY, str) else ENCRYPTION_KEY)

def encrypt_data(data: str) -> str:
    """
    Encrypts a string and returns the encrypted token as a string.
    """
    if not data: return ""
    encrypted_bytes = cipher_suite.encrypt(data.encode('utf-8'))
    return encrypted_bytes.decode('utf-8')

def decrypt_data(token: str) -> Optional[str]:
    """
    Decrypts a token and returns the original string.
    """
    if not token: return None
    try:
        decrypted_bytes = cipher_suite.decrypt(token.encode('utf-8'))
        return decrypted_bytes.decode('utf-8')
    except Exception as e:
        print(f"Decryption failed: {e}")
        return None

def rotate_key():
    """
    Example function to rotate keys (advanced).
    """
    global key, cipher_suite
    key = Fernet.generate_key()
    cipher_suite = Fernet(key)
    with open(ENCRYPTION_KEY_PATH, "wb") as key_file:
        key_file.write(key)
    print(f"New key generated and saved to {ENCRYPTION_KEY_PATH}")

if __name__ == "__main__":
    # Test
    original = "Jean Dupont - Patient Zero"
    encrypted = encrypt_data(original)
    decrypted = decrypt_data(encrypted)
    
    print(f"Original: {original}")
    print(f"Encrypted: {encrypted}")
    print(f"Decrypted: {decrypted}")
    assert original == decrypted