flare / utils /encryption_utils.py
ciyidogan's picture
Upload 134 files
edec17e verified
"""
Flare – Fernet şifreleme yardımcıları
- encrypt(): düz string → "enc:<blob>"
- decrypt(): enc:<blob> → düz string (veya enc: yoksa aynen döner)
Anahtar: FLARE_TOKEN_KEY (32-bayt, base64, URL-safe)
CLI Kullanımı:
python encryption_utils.py enc "şifrelenecek metin" [--key KEY]
python encryption_utils.py dec "enc:..." [--key KEY]
"""
import os
import sys
import argparse
from typing import Optional
from cryptography.fernet import Fernet, InvalidToken
try:
from .logger import log_error, log_warning
except ImportError:
# Fallback to simple print
def log_error(msg, error=None):
print(f"ERROR: {msg}", file=sys.stderr)
if error:
print(f"Details: {error}", file=sys.stderr)
def log_warning(msg):
print(f"WARNING: {msg}", file=sys.stderr)
_ENV_KEY = "FLARE_TOKEN_KEY"
def _get_key() -> Fernet:
"""Get encryption key with better error messages"""
# Direkt environment variable kullan
key = os.getenv(_ENV_KEY)
# .env dosyasından yüklemeyi dene
if not key:
try:
from dotenv import load_dotenv
load_dotenv()
key = os.getenv(_ENV_KEY)
except ImportError:
pass
if not key:
error_msg = (
f"{_ENV_KEY} ortam değişkeni tanımlanmadı. "
f"Lütfen 32-byte base64 key oluşturun: python generate_key.py"
)
log_error(error_msg)
raise RuntimeError(error_msg)
# Key formatını kontrol et
try:
return Fernet(key.encode())
except Exception as e:
error_msg = (
f"{_ENV_KEY} geçersiz format. "
f"32-byte base64 URL-safe key olmalı. "
f"Yeni key için: python generate_key.py"
)
log_error(error_msg, error=str(e))
raise RuntimeError(error_msg)
def encrypt(plain: str, key: Optional[str] = None) -> str:
"""düz string → enc:..."""
if not plain:
log_warning("Empty string passed to encrypt")
return ""
try:
if key:
f = Fernet(key.encode())
else:
f = _get_key()
encrypted = f.encrypt(plain.encode()).decode()
return "enc:" + encrypted
except Exception as e:
log_error("Encryption failed", error=str(e))
raise
def decrypt(value: Optional[str], key: Optional[str] = None) -> Optional[str]:
"""enc:... ise çözer, değilse aynen döndürür"""
if value is None or not isinstance(value, str):
return value
if not value.startswith("enc:"):
return value
token = value.split("enc:", 1)[1]
try:
if key:
f = Fernet(key.encode())
else:
f = _get_key()
decrypted = f.decrypt(token.encode()).decode()
return decrypted
except InvalidToken:
error_msg = (
"Şifre çözme başarısız. Muhtemel sebepler:\n"
"1. FLARE_TOKEN_KEY değişti\n"
"2. Şifreli veri bozuldu\n"
"3. Farklı bir key ile şifrelendi"
)
log_error(error_msg)
raise RuntimeError(error_msg)
except Exception as e:
log_error("Decryption error", error=str(e))
raise
def generate_key() -> str:
"""Generate a new Fernet encryption key"""
return Fernet.generate_key().decode()
def main():
"""CLI entry point"""
parser = argparse.ArgumentParser(
description="Fernet encryption/decryption utility",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Generate a new key
python encryption_utils.py keygen
# Save generated key to .env file
python encryption_utils.py keygen >> .env
# Then edit .env to add: FLARE_TOKEN_KEY=<generated-key>
# Encrypt with environment key
python encryption_utils.py enc "secret message"
# Encrypt with custom key
python encryption_utils.py enc "secret message" --key "your-32-byte-base64-key"
# Decrypt
python encryption_utils.py dec "enc:gAAAAABh..."
# Decrypt with custom key
python encryption_utils.py dec "enc:gAAAAABh..." --key "your-32-byte-base64-key"
"""
)
parser.add_argument(
"command",
choices=["enc", "dec", "keygen"],
help="Command to execute: 'enc' for encrypt, 'dec' for decrypt, 'keygen' to generate new key"
)
parser.add_argument(
"text",
nargs="?",
help="Text to encrypt or decrypt (not needed for keygen)"
)
parser.add_argument(
"--key",
help="Optional Fernet key (32-byte base64). If not provided, uses FLARE_TOKEN_KEY env var"
)
args = parser.parse_args()
try:
if args.command == "keygen":
key = generate_key()
print(key)
elif args.command == "enc":
if not args.text:
parser.error("Text is required for encryption")
result = encrypt(args.text, args.key)
print(result)
else: # dec
if not args.text:
parser.error("Text is required for decryption")
result = decrypt(args.text, args.key)
print(result)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()