Chapter 5: Cryptocurrency Wallets and Security

Haiyue
37min

Chapter 5: Cryptocurrency Wallets and Security

Learning Objectives
  • Understand how wallets work
  • Master the differences between hot wallets and cold wallets
  • Learn private key, public key, and mnemonic phrase management
  • Understand common security threats and protection measures

Wallet Fundamentals

Key Pair Generation and Management

Cryptocurrency wallets are essentially tools for managing key pairs and addresses:

import hashlib
import secrets
import hmac
from typing import List, Tuple, Dict
from dataclasses import dataclass

@dataclass
class KeyPair:
    """Key pair"""
    private_key: str
    public_key: str
    address: str

class CryptographicWallet:
    """Cryptocurrency wallet"""

    def __init__(self, entropy_bits: int = 128):
        """
        Initialize wallet
        entropy_bits: Entropy bits (128, 256, etc.)
        """
        self.entropy_bits = entropy_bits
        self.master_seed = None
        self.mnemonic = None
        self.accounts: Dict[str, KeyPair] = {}

    def generate_mnemonic(self, language: str = "english") -> List[str]:
        """Generate mnemonic phrase"""
        # Generate random entropy
        entropy = secrets.randbits(self.entropy_bits)
        entropy_bytes = entropy.to_bytes(self.entropy_bits // 8, 'big')

        # Calculate checksum
        checksum_bits = self.entropy_bits // 32
        hash_bytes = hashlib.sha256(entropy_bytes).digest()
        checksum = int.from_bytes(hash_bytes, 'big') >> (256 - checksum_bits)

        # Combine entropy and checksum
        total_bits = self.entropy_bits + checksum_bits
        combined = (entropy << checksum_bits) | checksum

        # Convert to mnemonic words (simplified implementation)
        word_count = total_bits // 11
        mnemonic_words = []

        # Simplified BIP39 word list (should contain full 2048 words)
        bip39_words = [
            "abandon", "ability", "able", "about", "above", "absent", "absorb",
            "abstract", "absurd", "abuse", "access", "accident", "account",
            "accuse", "achieve", "acid", "acoustic", "acquire", "across", "act",
            "action", "actor", "actress", "actual", "adapt", "add", "addict"
        ] * 80  # Extended to sufficient quantity

        for i in range(word_count):
            word_index = (combined >> (total_bits - (i + 1) * 11)) & 0x7FF
            word_index = word_index % len(bip39_words)
            mnemonic_words.append(bip39_words[word_index])

        self.mnemonic = mnemonic_words
        return mnemonic_words

    def create_seed_from_mnemonic(self, mnemonic: List[str],
                                  passphrase: str = "") -> bytes:
        """Generate seed from mnemonic phrase"""
        mnemonic_str = " ".join(mnemonic)
        salt = "mnemonic" + passphrase

        # Generate 512-bit seed using PBKDF2
        seed = hashlib.pbkdf2_hmac(
            'sha512',
            mnemonic_str.encode('utf-8'),
            salt.encode('utf-8'),
            2048,  # Iteration count
            64     # Output length (512 bits)
        )

        self.master_seed = seed
        return seed

    def derive_key_pair(self, derivation_path: str = "m/44'/0'/0'/0/0") -> KeyPair:
        """Generate key pair based on derivation path (simplified implementation)"""
        if not self.master_seed:
            raise ValueError("Must generate seed first")

        # Simplified key derivation (should use BIP32 standard)
        path_hash = hashlib.sha256(
            (derivation_path + str(len(self.accounts))).encode()
        ).digest()

        # Generate private key
        private_key_bytes = hmac.new(
            self.master_seed,
            path_hash,
            hashlib.sha256
        ).digest()

        private_key = private_key_bytes.hex()

        # Generate public key (simplified: using private key hash)
        public_key = hashlib.sha256(private_key_bytes).hexdigest()

        # Generate address (simplified: using RIPEMD160 of public key)
        address_bytes = hashlib.new(
            'ripemd160',
            bytes.fromhex(public_key)
        ).digest()
        address = "1" + address_bytes.hex()  # Simplified address format

        key_pair = KeyPair(private_key, public_key, address)
        self.accounts[address] = key_pair

        return key_pair

    def sign_transaction(self, private_key: str, transaction_data: str) -> str:
        """Sign transaction (simplified implementation)"""
        # Should use ECDSA algorithm
        signature = hmac.new(
            bytes.fromhex(private_key),
            transaction_data.encode(),
            hashlib.sha256
        ).hexdigest()

        return signature

    def verify_signature(self, public_key: str, transaction_data: str,
                        signature: str) -> bool:
        """Verify signature (simplified implementation)"""
        # This is simplified, actual implementation needs elliptic curve cryptography
        return len(signature) == 64  # Simple length check

    def export_wallet(self, password: str) -> Dict:
        """Export wallet (encrypted)"""
        if not self.mnemonic:
            raise ValueError("Wallet not initialized")

        # Encrypt mnemonic
        encrypted_mnemonic = self._encrypt_data(" ".join(self.mnemonic), password)

        wallet_data = {
            "version": "1.0",
            "encrypted_mnemonic": encrypted_mnemonic,
            "accounts": {
                addr: {
                    "address": kp.address,
                    "public_key": kp.public_key
                    # Don't export private key, re-derive from mnemonic
                }
                for addr, kp in self.accounts.items()
            }
        }

        return wallet_data

    def import_wallet(self, wallet_data: Dict, password: str):
        """Import wallet"""
        try:
            # Decrypt mnemonic
            encrypted_mnemonic = wallet_data["encrypted_mnemonic"]
            mnemonic_str = self._decrypt_data(encrypted_mnemonic, password)
            self.mnemonic = mnemonic_str.split()

            # Regenerate seed and keys
            self.create_seed_from_mnemonic(self.mnemonic)

            # Re-derive accounts
            for i in range(len(wallet_data["accounts"])):
                self.derive_key_pair(f"m/44'/0'/0'/0/{i}")

            print("Wallet import successful")

        except Exception as e:
            raise ValueError(f"Wallet import failed: {e}")

    def _encrypt_data(self, data: str, password: str) -> str:
        """Encrypt data (simplified implementation)"""
        # Should use strong encryption like AES
        password_hash = hashlib.sha256(password.encode()).digest()
        encrypted = bytes(a ^ b for a, b in zip(data.encode(), password_hash[:len(data.encode())]))
        return encrypted.hex()

    def _decrypt_data(self, encrypted_hex: str, password: str) -> str:
        """Decrypt data (simplified implementation)"""
        encrypted = bytes.fromhex(encrypted_hex)
        password_hash = hashlib.sha256(password.encode()).digest()
        decrypted = bytes(a ^ b for a, b in zip(encrypted, password_hash[:len(encrypted)]))
        return decrypted.decode()

# Wallet usage demonstration
print("=== Cryptocurrency Wallet Demo ===")

# Create new wallet
wallet = CryptographicWallet(entropy_bits=128)

# Generate mnemonic
mnemonic = wallet.generate_mnemonic()
print(f"Mnemonic: {' '.join(mnemonic)}")

# Generate seed
seed = wallet.create_seed_from_mnemonic(mnemonic)
print(f"Seed (hex): {seed.hex()[:32]}...")

# Derive key pairs
key_pair1 = wallet.derive_key_pair("m/44'/0'/0'/0/0")
key_pair2 = wallet.derive_key_pair("m/44'/0'/0'/0/1")

print(f"\nAccount 1:")
print(f"  Address: {key_pair1.address}")
print(f"  Public Key: {key_pair1.public_key[:16]}...")
print(f"  Private Key: {key_pair1.private_key[:16]}...")

print(f"\nAccount 2:")
print(f"  Address: {key_pair2.address}")

# Sign transaction
tx_data = "Alice sends 1 BTC to Bob"
signature = wallet.sign_transaction(key_pair1.private_key, tx_data)
print(f"\nTransaction Signature: {signature[:16]}...")

# Verify signature
is_valid = wallet.verify_signature(key_pair1.public_key, tx_data, signature)
print(f"Signature Verification: {is_valid}")

Wallet Type Classification

Hot Wallets vs Cold Wallets

from enum import Enum
import time
from abc import ABC, abstractmethod

class WalletType(Enum):
    """Wallet types"""
    HOT = "hot_wallet"          # Hot wallet
    COLD = "cold_wallet"        # Cold wallet
    HARDWARE = "hardware_wallet"  # Hardware wallet
    PAPER = "paper_wallet"      # Paper wallet

class BaseWallet(ABC):
    """Base wallet class"""

    def __init__(self, wallet_type: WalletType):
        self.wallet_type = wallet_type
        self.created_at = time.time()
        self.last_backup = None

    @abstractmethod
    def create_transaction(self, to_address: str, amount: float) -> Dict:
        pass

    @abstractmethod
    def sign_transaction(self, transaction: Dict) -> str:
        pass

    @abstractmethod
    def get_security_level(self) -> int:
        pass

class HotWallet(BaseWallet):
    """Hot wallet (online)"""

    def __init__(self):
        super().__init__(WalletType.HOT)
        self.is_online = True
        self.auto_sync = True
        self.convenience_features = ["Quick transactions", "Real-time prices", "DApp connection"]

    def create_transaction(self, to_address: str, amount: float) -> Dict:
        """Create transaction (hot wallet)"""
        transaction = {
            "from": "hot_wallet_address",
            "to": to_address,
            "amount": amount,
            "timestamp": time.time(),
            "gas_price": self._get_current_gas_price(),
            "nonce": self._get_account_nonce()
        }

        print(f"Hot wallet transaction created: {amount} -> {to_address}")
        print(f"Current Gas price: {transaction['gas_price']} Gwei")

        return transaction

    def sign_transaction(self, transaction: Dict) -> str:
        """Sign transaction"""
        # Hot wallet can sign immediately
        signature = f"hot_sig_{hash(str(transaction)) % 100000}"
        print(f"Hot wallet instant signature: {signature}")
        return signature

    def get_security_level(self) -> int:
        """Security level (1-10)"""
        return 6  # Medium security

    def connect_to_dapp(self, dapp_url: str) -> bool:
        """Connect to DApp"""
        if self.is_online:
            print(f"Connected to DApp: {dapp_url}")
            return True
        return False

    def _get_current_gas_price(self) -> float:
        """Get current gas price"""
        # Simulate fetching real-time gas price from network
        return 25.0  # Gwei

    def _get_account_nonce(self) -> int:
        """Get account nonce"""
        return int(time.time()) % 1000

class ColdWallet(BaseWallet):
    """Cold wallet (offline)"""

    def __init__(self):
        super().__init__(WalletType.COLD)
        self.is_online = False
        self.air_gapped = True  # Air-gapped
        self.security_features = ["Offline storage", "Multi-signature", "Backup mechanism"]

    def create_transaction(self, to_address: str, amount: float) -> Dict:
        """Create transaction (cold wallet)"""
        # Cold wallet requires manual network parameters
        transaction = {
            "from": "cold_wallet_address",
            "to": to_address,
            "amount": amount,
            "timestamp": time.time(),
            "gas_price": self._get_manual_gas_price(),
            "nonce": self._get_manual_nonce()
        }

        print(f"Cold wallet transaction created: {amount} -> {to_address}")
        print("Warning: Manual network parameter setting required")

        return transaction

    def sign_transaction(self, transaction: Dict) -> str:
        """Offline sign transaction"""
        print("Starting offline signing process...")
        print("1. Verify transaction details")
        print("2. Confirm signing operation")
        print("3. Generate signature")

        signature = f"cold_sig_{hash(str(transaction)) % 100000}"
        print(f"Cold wallet offline signing completed: {signature}")
        return signature

    def get_security_level(self) -> int:
        """Security level (1-10)"""
        return 10  # Maximum security

    def export_signed_transaction(self, transaction: Dict, signature: str) -> str:
        """Export signed transaction"""
        signed_tx = {
            "transaction": transaction,
            "signature": signature,
            "export_time": time.time()
        }

        # Simulate export as QR code or file
        export_data = f"signed_tx_{hash(str(signed_tx)) % 100000}.txt"
        print(f"Signed transaction exported: {export_data}")
        return export_data

    def _get_manual_gas_price(self) -> float:
        """Manually set gas price"""
        # Cold wallet user needs to manually query and input
        return 30.0  # Gwei

    def _get_manual_nonce(self) -> int:
        """Manually set nonce"""
        return 42  # User manual input

class HardwareWallet(BaseWallet):
    """Hardware wallet"""

    def __init__(self, device_model: str):
        super().__init__(WalletType.HARDWARE)
        self.device_model = device_model
        self.firmware_version = "1.0.0"
        self.is_connected = False
        self.pin_required = True

    def connect_device(self, pin: str) -> bool:
        """Connect hardware device"""
        if self._verify_pin(pin):
            self.is_connected = True
            print(f"Success: {self.device_model} connected")
            return True
        else:
            print("Error: Incorrect PIN")
            return False

    def create_transaction(self, to_address: str, amount: float) -> Dict:
        """Create transaction"""
        if not self.is_connected:
            raise Exception("Hardware wallet not connected")

        transaction = {
            "from": "hardware_wallet_address",
            "to": to_address,
            "amount": amount,
            "timestamp": time.time()
        }

        print(f"Hardware wallet transaction prepared: {amount} -> {to_address}")
        return transaction

    def sign_transaction(self, transaction: Dict) -> str:
        """Hardware signature"""
        if not self.is_connected:
            raise Exception("Hardware wallet not connected")

        print("Please confirm transaction on hardware device...")
        print("1. Verify recipient address")
        print("2. Confirm transaction amount")
        print("3. Press confirm button")

        # Simulate user confirmation
        user_confirmed = True  # Actual implementation needs hardware interaction

        if user_confirmed:
            signature = f"hw_sig_{hash(str(transaction)) % 100000}"
            print(f"Success: Hardware signature completed: {signature}")
            return signature
        else:
            raise Exception("User cancelled transaction")

    def get_security_level(self) -> int:
        """Security level"""
        return 9  # High security

    def _verify_pin(self, pin: str) -> bool:
        """Verify PIN"""
        return len(pin) >= 4  # Simplified verification

# Wallet type comparison demonstration
print("\n=== Wallet Type Comparison Demo ===")

# Create different types of wallets
hot_wallet = HotWallet()
cold_wallet = ColdWallet()
hardware_wallet = HardwareWallet("Ledger Nano S")

wallets = [
    ("Hot Wallet", hot_wallet),
    ("Cold Wallet", cold_wallet),
    ("Hardware Wallet", hardware_wallet)
]

# Compare wallet features
print("Wallet Feature Comparison:")
print(f"{'Wallet Type':15} {'Security':10} {'Convenience':12} {'Use Case':25}")
print("-" * 65)

wallet_features = {
    "Hot Wallet": {"Security": 6, "Convenience": 10, "Use Case": "Daily small transactions"},
    "Cold Wallet": {"Security": 10, "Convenience": 3, "Use Case": "Long-term storage"},
    "Hardware Wallet": {"Security": 9, "Convenience": 7, "Use Case": "Frequent trading + security"}
}

for wallet_name, features in wallet_features.items():
    print(f"{wallet_name:15} {features['Security']:10} {features['Convenience']:12} {features['Use Case']:25}")

# Simulate transaction process comparison
print(f"\n=== Transaction Process Comparison ===")

transaction_details = {
    "to_address": "1ABC...xyz",
    "amount": 0.5
}

for wallet_name, wallet in wallets:
    print(f"\n{wallet_name} Transaction Process:")
    try:
        if wallet_name == "Hardware Wallet":
            wallet.connect_device("1234")

        tx = wallet.create_transaction(**transaction_details)
        signature = wallet.sign_transaction(tx)
        print(f"Security Level: {wallet.get_security_level()}/10")

    except Exception as e:
        print(f"Transaction failed: {e}")

Mnemonic Phrase and Seed Management

BIP39 Mnemonic Standard

import secrets
import hashlib
from typing import List, Optional

class BIP39:
    """BIP39 mnemonic standard implementation"""

    # Simplified BIP39 word list (actual standard contains 2048 words)
    WORDLIST = [
        "abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract",
        "absurd", "abuse", "access", "accident", "account", "accuse", "achieve", "acid",
        "acoustic", "acquire", "across", "act", "action", "actor", "actress", "actual",
        "adapt", "add", "addict", "address", "adjust", "admit", "adult", "advance",
        # ... should contain 2048 words
    ] * 64  # Extended to 2048

    @classmethod
    def generate_mnemonic(cls, strength: int = 128) -> List[str]:
        """
        Generate mnemonic phrase
        strength: Entropy strength (128, 160, 192, 224, 256)
        """
        if strength not in [128, 160, 192, 224, 256]:
            raise ValueError("Strength must be 128, 160, 192, 224, or 256")

        # Generate random entropy
        entropy_bytes = secrets.randbits(strength).to_bytes(strength // 8, 'big')

        # Calculate checksum
        checksum_length = strength // 32
        hash_bytes = hashlib.sha256(entropy_bytes).digest()
        checksum = int.from_bytes(hash_bytes, 'big') >> (256 - checksum_length)

        # Combine entropy and checksum
        entropy_with_checksum = (int.from_bytes(entropy_bytes, 'big') << checksum_length) | checksum
        total_bits = strength + checksum_length

        # Convert to mnemonic words
        mnemonic_length = total_bits // 11
        mnemonic = []

        for i in range(mnemonic_length):
            word_index = (entropy_with_checksum >> (total_bits - (i + 1) * 11)) & 0x7FF
            word_index = word_index % len(cls.WORDLIST)
            mnemonic.append(cls.WORDLIST[word_index])

        return mnemonic

    @classmethod
    def mnemonic_to_seed(cls, mnemonic: List[str], passphrase: str = "") -> bytes:
        """Convert mnemonic phrase to seed"""
        mnemonic_str = " ".join(mnemonic)
        salt = "mnemonic" + passphrase

        # Use PBKDF2-HMAC-SHA512
        seed = hashlib.pbkdf2_hmac(
            'sha512',
            mnemonic_str.encode('utf-8'),
            salt.encode('utf-8'),
            2048,  # Iteration count
            64     # Output length (512 bits)
        )

        return seed

    @classmethod
    def validate_mnemonic(cls, mnemonic: List[str]) -> bool:
        """Validate mnemonic phrase"""
        if len(mnemonic) not in [12, 15, 18, 21, 24]:
            return False

        # Check if words are in wordlist
        for word in mnemonic:
            if word not in cls.WORDLIST:
                return False

        # Validate checksum (simplified implementation)
        return True

    @classmethod
    def get_entropy_from_mnemonic(cls, mnemonic: List[str]) -> bytes:
        """Recover entropy from mnemonic phrase"""
        if not cls.validate_mnemonic(mnemonic):
            raise ValueError("Invalid mnemonic phrase")

        # Convert to bit sequence
        total_bits = len(mnemonic) * 11
        entropy_bits = (total_bits * 32) // 33

        combined = 0
        for word in mnemonic:
            word_index = cls.WORDLIST.index(word)
            combined = (combined << 11) | word_index

        # Extract entropy
        entropy = combined >> (total_bits - entropy_bits)
        entropy_bytes = entropy.to_bytes(entropy_bits // 8, 'big')

        return entropy_bytes

class SecureMnemonicStorage:
    """Secure mnemonic storage"""

    def __init__(self):
        self.encrypted_storage = {}

    def store_mnemonic(self, mnemonic: List[str], password: str,
                      storage_id: str) -> Dict:
        """Securely store mnemonic phrase"""
        # Generate storage key
        storage_key = self._derive_storage_key(password, storage_id)

        # Encrypt mnemonic
        mnemonic_str = " ".join(mnemonic)
        encrypted_mnemonic = self._encrypt_aes(mnemonic_str, storage_key)

        # Generate checksum
        checksum = hashlib.sha256(mnemonic_str.encode()).hexdigest()[:8]

        storage_data = {
            "encrypted_mnemonic": encrypted_mnemonic.hex(),
            "checksum": checksum,
            "timestamp": time.time(),
            "version": "1.0"
        }

        self.encrypted_storage[storage_id] = storage_data

        return {
            "storage_id": storage_id,
            "checksum": checksum,
            "status": "success"
        }

    def retrieve_mnemonic(self, storage_id: str, password: str) -> List[str]:
        """Retrieve mnemonic phrase"""
        if storage_id not in self.encrypted_storage:
            raise ValueError("Storage ID does not exist")

        storage_data = self.encrypted_storage[storage_id]

        # Generate decryption key
        storage_key = self._derive_storage_key(password, storage_id)

        try:
            # Decrypt mnemonic
            encrypted_bytes = bytes.fromhex(storage_data["encrypted_mnemonic"])
            decrypted_str = self._decrypt_aes(encrypted_bytes, storage_key)

            # Verify checksum
            checksum = hashlib.sha256(decrypted_str.encode()).hexdigest()[:8]
            if checksum != storage_data["checksum"]:
                raise ValueError("Checksum verification failed")

            mnemonic = decrypted_str.split()

            # Validate mnemonic
            if not BIP39.validate_mnemonic(mnemonic):
                raise ValueError("Mnemonic validation failed")

            return mnemonic

        except Exception as e:
            raise ValueError(f"Mnemonic retrieval failed: {e}")

    def _derive_storage_key(self, password: str, storage_id: str) -> bytes:
        """Derive storage key"""
        salt = storage_id.encode('utf-8')
        key = hashlib.pbkdf2_hmac(
            'sha256',
            password.encode('utf-8'),
            salt,
            100000,  # Iteration count
            32       # Key length
        )
        return key

    def _encrypt_aes(self, plaintext: str, key: bytes) -> bytes:
        """AES encryption (simplified implementation)"""
        # Should use authenticated encryption modes like AES-GCM
        data = plaintext.encode('utf-8')
        key_hash = hashlib.sha256(key).digest()
        encrypted = bytes(a ^ b for a, b in zip(data, key_hash[:len(data)]))
        return encrypted

    def _decrypt_aes(self, ciphertext: bytes, key: bytes) -> str:
        """AES decryption (simplified implementation)"""
        key_hash = hashlib.sha256(key).digest()
        decrypted = bytes(a ^ b for a, b in zip(ciphertext, key_hash[:len(ciphertext)]))
        return decrypted.decode('utf-8')

# Mnemonic management demonstration
print("\n=== Mnemonic Management Demo ===")

# Generate mnemonics with different strengths
print("Generate mnemonics with different strengths:")
for strength in [128, 192, 256]:
    mnemonic = BIP39.generate_mnemonic(strength)
    word_count = len(mnemonic)
    print(f"{strength}-bit entropy ({word_count} words): {' '.join(mnemonic[:4])}...")

# Full mnemonic example
sample_mnemonic = BIP39.generate_mnemonic(128)
print(f"\nFull mnemonic example: {' '.join(sample_mnemonic)}")

# Generate seed
seed = BIP39.mnemonic_to_seed(sample_mnemonic)
print(f"Seed (hex): {seed.hex()}")

# Seed generation with passphrase
seed_with_passphrase = BIP39.mnemonic_to_seed(sample_mnemonic, "MySecretPassphrase")
print(f"Seed with passphrase: {seed_with_passphrase.hex()}")

# Secure storage demonstration
print(f"\n=== Secure Mnemonic Storage Demo ===")

storage = SecureMnemonicStorage()

# Store mnemonic
storage_result = storage.store_mnemonic(
    mnemonic=sample_mnemonic,
    password="MyStrongPassword123!",
    storage_id="wallet_backup_001"
)

print(f"Storage result: {storage_result}")

# Retrieve mnemonic
try:
    retrieved_mnemonic = storage.retrieve_mnemonic(
        storage_id="wallet_backup_001",
        password="MyStrongPassword123!"
    )
    print(f"Retrieval successful: {retrieved_mnemonic == sample_mnemonic}")
    print(f"Retrieved mnemonic: {' '.join(retrieved_mnemonic[:4])}...")

except ValueError as e:
    print(f"Retrieval failed: {e}")

Common Security Threats and Protection

Security Threat Classification

from enum import Enum
from typing import Dict, List
import re

class ThreatLevel(Enum):
    """Threat levels"""
    LOW = 1
    MEDIUM = 2
    HIGH = 3
    CRITICAL = 4

class ThreatType(Enum):
    """Threat types"""
    PHISHING = "Phishing Attack"
    MALWARE = "Malware"
    SOCIAL_ENGINEERING = "Social Engineering"
    MAN_IN_THE_MIDDLE = "Man-in-the-Middle Attack"
    CLIPBOARD_HIJACKING = "Clipboard Hijacking"
    FAKE_WALLET = "Fake Wallet"
    PRIVATE_KEY_EXPOSURE = "Private Key Exposure"
    WEAK_PASSWORD = "Weak Password"

@dataclass
class SecurityThreat:
    """Security threat"""
    threat_type: ThreatType
    level: ThreatLevel
    description: str
    attack_vectors: List[str]
    prevention_measures: List[str]

class SecurityAnalyzer:
    """Security analyzer"""

    def __init__(self):
        self.known_threats = self._initialize_threats()
        self.security_patterns = self._initialize_patterns()

    def _initialize_threats(self) -> Dict[ThreatType, SecurityThreat]:
        """Initialize threat database"""
        threats = {
            ThreatType.PHISHING: SecurityThreat(
                threat_type=ThreatType.PHISHING,
                level=ThreatLevel.HIGH,
                description="Stealing user credentials through fake websites or emails",
                attack_vectors=[
                    "Fake exchange websites",
                    "Phishing emails",
                    "Social media links",
                    "Malicious ads"
                ],
                prevention_measures=[
                    "Verify website SSL certificate",
                    "Check URL spelling",
                    "Use official apps",
                    "Enable two-factor authentication"
                ]
            ),

            ThreatType.MALWARE: SecurityThreat(
                threat_type=ThreatType.MALWARE,
                level=ThreatLevel.CRITICAL,
                description="Malicious software stealing private keys or tampering with transactions",
                attack_vectors=[
                    "Keyloggers",
                    "Clipboard viruses",
                    "Fake wallet software",
                    "Browser extensions"
                ],
                prevention_measures=[
                    "Use antivirus software",
                    "Regular system scans",
                    "Download software only from official sources",
                    "Use hardware wallet"
                ]
            ),

            ThreatType.CLIPBOARD_HIJACKING: SecurityThreat(
                threat_type=ThreatType.CLIPBOARD_HIJACKING,
                level=ThreatLevel.HIGH,
                description="Malware replacing addresses in clipboard",
                attack_vectors=[
                    "Memory-resident viruses",
                    "Background monitoring programs",
                    "Browser extension hijacking"
                ],
                prevention_measures=[
                    "Manually verify addresses",
                    "Use address book",
                    "Verify in segments",
                    "Confirm with hardware wallet"
                ]
            )
        }

        return threats

    def _initialize_patterns(self) -> Dict[str, re.Pattern]:
        """Initialize security pattern matching"""
        return {
            "suspicious_url": re.compile(r".*\.(tk|ml|ga|cf)/.*|.*xn--.*"),
            "weak_password": re.compile(r"^.{0,7}$|^[a-z]+$|^[A-Z]+$|^[0-9]+$"),
            "bitcoin_address": re.compile(r"^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$"),
            "ethereum_address": re.compile(r"^0x[a-fA-F0-9]{40}$")
        }

    def analyze_url_safety(self, url: str) -> Dict:
        """Analyze URL safety"""
        risk_score = 0
        warnings = []

        # Check suspicious domains
        if self.security_patterns["suspicious_url"].match(url):
            risk_score += 30
            warnings.append("Suspicious top-level domain")

        # Check HTTPS
        if not url.startswith("https://"):
            risk_score += 20
            warnings.append("Not using HTTPS encryption")

        # Check common phishing patterns
        phishing_patterns = [
            "bin4nce", "coinb4se", "block-chain",
            "meta-mask", "my-ether-wallet"
        ]

        for pattern in phishing_patterns:
            if pattern in url.lower():
                risk_score += 50
                warnings.append(f"Phishing pattern detected: {pattern}")

        # Assess risk level
        if risk_score >= 50:
            risk_level = ThreatLevel.CRITICAL
        elif risk_score >= 30:
            risk_level = ThreatLevel.HIGH
        elif risk_score >= 15:
            risk_level = ThreatLevel.MEDIUM
        else:
            risk_level = ThreatLevel.LOW

        return {
            "url": url,
            "risk_score": risk_score,
            "risk_level": risk_level,
            "warnings": warnings,
            "safe": risk_score < 15
        }

    def validate_address(self, address: str, currency: str = "bitcoin") -> Dict:
        """Validate address format"""
        if currency.lower() == "bitcoin":
            pattern = self.security_patterns["bitcoin_address"]
        elif currency.lower() == "ethereum":
            pattern = self.security_patterns["ethereum_address"]
        else:
            return {"valid": False, "error": "Unsupported currency type"}

        is_valid = bool(pattern.match(address))

        return {
            "address": address,
            "currency": currency,
            "valid": is_valid,
            "format_check": "Pass" if is_valid else "Fail"
        }

    def check_password_strength(self, password: str) -> Dict:
        """Check password strength"""
        score = 0
        recommendations = []

        # Length check
        if len(password) >= 12:
            score += 25
        elif len(password) >= 8:
            score += 15
        else:
            recommendations.append("Password should be at least 8 characters, 12+ recommended")

        # Character complexity
        if re.search(r"[a-z]", password):
            score += 10
        else:
            recommendations.append("Include lowercase letters")

        if re.search(r"[A-Z]", password):
            score += 10
        else:
            recommendations.append("Include uppercase letters")

        if re.search(r"[0-9]", password):
            score += 10
        else:
            recommendations.append("Include numbers")

        if re.search(r"[!@#$%^&*(),.?\":{}|<>]", password):
            score += 15
        else:
            recommendations.append("Include special characters")

        # Common pattern check
        common_patterns = ["123456", "password", "qwerty", "abc", "111"]
        for pattern in common_patterns:
            if pattern in password.lower():
                score -= 20
                recommendations.append("Avoid common patterns")
                break

        # Rating
        if score >= 70:
            strength = "Strong"
        elif score >= 50:
            strength = "Medium"
        elif score >= 30:
            strength = "Weak"
        else:
            strength = "Very Weak"

        return {
            "score": max(0, score),
            "strength": strength,
            "recommendations": recommendations
        }

    def security_checklist(self) -> Dict:
        """Security checklist"""
        return {
            "Wallet Security": [
                "Use hardware wallet for large amounts",
                "Regular mnemonic backups",
                "Use strong passwords and 2FA",
                "Verify software source and integrity"
            ],
            "Transaction Security": [
                "Double-check recipient address",
                "Verify transaction fee reasonableness",
                "Test with small amount before large transfer",
                "Use trusted RPC nodes"
            ],
            "Network Security": [
                "Use VPN for privacy protection",
                "Avoid public WiFi for transactions",
                "Regular software and system updates",
                "Use official websites and apps"
            ],
            "Storage Security": [
                "Multiple mnemonic backups",
                "Physical secure storage",
                "Avoid digital private key storage",
                "Regular backup validity checks"
            ]
        }

# Security analysis demonstration
print("\n=== Cryptocurrency Security Analysis Demo ===")

analyzer = SecurityAnalyzer()

# URL safety analysis
test_urls = [
    "https://www.binance.com",
    "http://bin4nce.tk/login",
    "https://metamask.io",
    "https://my-ether-wallet.com"
]

print("URL Safety Analysis:")
for url in test_urls:
    result = analyzer.analyze_url_safety(url)
    safety_status = "Safe" if result["safe"] else "Warning: Dangerous"
    print(f"  {url}")
    print(f"    {safety_status} (Risk score: {result['risk_score']})")
    if result["warnings"]:
        print(f"    Warnings: {', '.join(result['warnings'])}")
    print()

# Address validation
print("Address Format Validation:")
test_addresses = [
    ("1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2", "bitcoin"),
    ("0x742d35Cc6634C0532925a3b8D45d70c55e7c8f08", "ethereum"),
    ("invalid_address_123", "bitcoin")
]

for address, currency in test_addresses:
    result = analyzer.validate_address(address, currency)
    status = "Valid" if result["valid"] else "Invalid"
    print(f"  {address[:20]}... ({currency}): {status}")

# Password strength check
print("\nPassword Strength Analysis:")
test_passwords = [
    "password123",
    "MyStr0ng!P@ssw0rd2024",
    "abc123",
    "Blockchain$Security#2024"
]

for password in test_passwords:
    result = analyzer.check_password_strength(password)
    print(f"  Password: {'*' * len(password)}")
    print(f"    Strength: {result['strength']} ({result['score']}/100)")
    if result["recommendations"]:
        print(f"    Recommendations: {', '.join(result['recommendations'][:2])}")
    print()

# Security checklist
print("=== Security Checklist ===")
checklist = analyzer.security_checklist()
for category, items in checklist.items():
    print(f"\n{category}:")
    for item in items:
        print(f"  - {item}")

Chapter Summary

This chapter comprehensively covered cryptocurrency wallets and security management:

  1. Wallet Fundamentals:

    • Key pair generation and management
    • Mnemonic phrase and seed mechanism
    • Address derivation algorithms
  2. Wallet Types:

    • Hot Wallets: Convenient but higher risk
    • Cold Wallets: Secure but less convenient
    • Hardware Wallets: Balance between security and convenience
  3. Mnemonic Management:

    • BIP39 standard implementation
    • Secure storage and recovery
    • Passphrase protection
  4. Security Threat Protection:

    • Phishing attack identification
    • Malware protection
    • Password security management
    • Address verification mechanisms
  5. Best Practices:

    • Multiple backup strategies
    • Security checklists
    • Tiered storage solutions
    • Regular security audits

Understanding and mastering these security concepts is crucial for safely using cryptocurrencies. In the next chapter, we will learn about the fundamentals of cryptocurrency transactions.