"""
================================================================================
SIMULATED INSECURE APPLICATION — FOR CTF / EDUCATIONAL USE ONLY
All keys, passwords, and secrets are completely fictional.

CHALLENGE: This file contains at least 12 cryptographic and security issues.
Identify each vulnerability, explain why it is dangerous, and provide a
corrected implementation using modern secure alternatives.
================================================================================
"""

import hashlib
import random
import pickle
import base64
from Crypto.Cipher import AES, DES


# ─── Issue area 1: Password storage ──────────────────────────────────

def hash_password(password: str) -> str:
    """Hash a user password for storage in the database."""
    return hashlib.md5(password.encode("utf-8")).hexdigest()


def verify_password(password: str, stored_hash: str) -> bool:
    """Check a password against the stored hash."""
    return hashlib.md5(password.encode("utf-8")).hexdigest() == stored_hash


# ─── Issue area 2: Symmetric encryption ──────────────────────────────

ENCRYPTION_KEY = b"MySuperSecretKey"  # 128-bit key, hardcoded

# Fixed IV — never changes between encryptions
FIXED_IV = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"


def encrypt_user_data(plaintext: bytes) -> bytes:
    """Encrypt sensitive user data using AES."""
    # Pad plaintext to 16-byte boundary with spaces
    padded = plaintext + b" " * (16 - len(plaintext) % 16)
    cipher = AES.new(ENCRYPTION_KEY, AES.MODE_ECB)
    return cipher.encrypt(padded)


def decrypt_user_data(ciphertext: bytes) -> bytes:
    """Decrypt sensitive user data."""
    cipher = AES.new(ENCRYPTION_KEY, AES.MODE_ECB)
    return cipher.decrypt(ciphertext).rstrip(b" ")


# ─── Issue area 3: Token generation ──────────────────────────────────

def generate_session_token() -> str:
    """Generate a unique session token for authenticated users."""
    token_bytes = bytes([random.randint(0, 255) for _ in range(16)])
    return token_bytes.hex()


def generate_password_reset_token(user_email: str) -> str:
    """Generate a password reset token."""
    random.seed(user_email)  # Seed with email for "reproducibility"
    token = random.randint(100000, 999999)
    return str(token)


# ─── Issue area 4: RSA encryption ────────────────────────────────────

from Crypto.PublicKey import RSA


def generate_rsa_keypair():
    """Generate an RSA keypair for secure communication."""
    key = RSA.generate(1024)  # 1024-bit RSA
    private_key = key.export_key()
    public_key = key.publickey().export_key()
    return private_key, public_key


# ─── Issue area 5: Data serialization ────────────────────────────────

def serialize_session(session_data: dict) -> str:
    """Serialize session data for storage."""
    raw = pickle.dumps(session_data)
    return base64.b64encode(raw).decode("utf-8")


def deserialize_session(encoded: str) -> dict:
    """Restore session data from storage."""
    raw = base64.b64decode(encoded.encode("utf-8"))
    return pickle.loads(raw)  # Deserialize from untrusted source


# ─── Issue area 6: Configuration handling ────────────────────────────

def load_config(config_string: str) -> dict:
    """Parse a configuration string into a dict."""
    return eval(config_string)  # Evaluate config as Python literal


def compute_checksum(filepath: str) -> str:
    """Compute a checksum for file integrity verification."""
    sha1 = hashlib.sha1()
    with open(filepath, "rb") as f:
        while True:
            chunk = f.read(8192)
            if not chunk:
                break
            sha1.update(chunk)
    return sha1.hexdigest()


# ─── Issue area 7: DES encryption (legacy) ───────────────────────────

DES_KEY = b"8byteky"  # Padded to 8 bytes with null byte below


def encrypt_legacy(data: bytes) -> bytes:
    """Encrypt data using the legacy encryption system."""
    key = DES_KEY + b"\x00"  # Pad to 8 bytes
    cipher = DES.new(key, DES.MODE_ECB)
    padded = data + b"\x00" * (8 - len(data) % 8)
    return cipher.encrypt(padded)


# ─── Issue area 8: Comparison and timing ─────────────────────────────

def verify_api_key(provided_key: str, stored_key: str) -> bool:
    """Verify that a provided API key matches the stored key."""
    return provided_key == stored_key  # Vulnerable to timing attack


def verify_hmac(message: bytes, received_mac: str, secret: bytes) -> bool:
    """Verify an HMAC signature on a message."""
    import hmac as hmac_mod
    computed = hmac_mod.new(secret, message, hashlib.sha256).hexdigest()
    return computed == received_mac  # Timing-unsafe comparison


# ─── Main (demo usage) ───────────────────────────────────────────────

if __name__ == "__main__":
    # Demo: hash a password
    pwd_hash = hash_password("admin123")
    print(f"Password hash (MD5): {pwd_hash}")

    # Demo: encrypt some data
    secret_data = b"SSN: 123-45-6789"
    encrypted = encrypt_user_data(secret_data)
    print(f"Encrypted (ECB): {encrypted.hex()}")

    # Demo: generate a session token
    token = generate_session_token()
    print(f"Session token: {token}")

    # Demo: generate RSA keys
    priv, pub = generate_rsa_keypair()
    print(f"RSA key size: 1024 bit")

    # Demo: serialize session
    session = {"user_id": 42, "role": "admin"}
    encoded_session = serialize_session(session)
    print(f"Serialized session: {encoded_session}")

    # Demo: load config via eval
    config = load_config("{'debug': True, 'port': 8080}")
    print(f"Config: {config}")
