import hashlib import secrets import ecdsa from bitcoin import privtopub, pubtoaddr from cryptography.fernet import Fernet from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC import base64 import os from typing import Tuple, Dict from web3 import Web3 class CryptoUtils: @staticmethod def generate_encryption_key(password: str, salt: bytes = None) -> bytes: if salt is None: salt = os.urandom(16) kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=salt, iterations=100000, ) key = base64.urlsafe_b64encode(kdf.derive(password.encode())) return key @staticmethod def encrypt_private_key(private_key: str, password: str) -> str: salt = os.urandom(16) key = CryptoUtils.generate_encryption_key(password, salt) f = Fernet(key) encrypted = f.encrypt(private_key.encode()) # Combine salt and encrypted data return base64.b64encode(salt + encrypted).decode() @staticmethod def decrypt_private_key(encrypted_key: str, password: str) -> str: data = base64.b64decode(encrypted_key.encode()) salt = data[:16] encrypted = data[16:] key = CryptoUtils.generate_encryption_key(password, salt) f = Fernet(key) decrypted = f.decrypt(encrypted) return decrypted.decode() class BitcoinWallet: @staticmethod def generate_wallet() -> Tuple[str, str]: # Generate private key private_key = secrets.randbits(256) private_key_hex = hex(private_key)[2:].zfill(64) # Generate public key and address public_key = privtopub(private_key_hex) address = pubtoaddr(public_key) return private_key_hex, address @staticmethod def sign_transaction(private_key_hex: str, transaction_data: Dict) -> str: # Simplified transaction signing for Bitcoin # In production, use proper Bitcoin transaction libraries message = str(transaction_data).encode() message_hash = hashlib.sha256(message).digest() private_key_int = int(private_key_hex, 16) signing_key = ecdsa.SigningKey.from_string( private_key_int.to_bytes(32, byteorder='big'), curve=ecdsa.SECP256k1 ) signature = signing_key.sign(message_hash) return signature.hex() @staticmethod def verify_address(address: str) -> bool: # Basic Bitcoin address validation try: if len(address) < 26 or len(address) > 35: return False return address.startswith(('1', '3', 'bc1')) except Exception: return False class EthereumWallet: @staticmethod def generate_wallet() -> Tuple[str, str]: # Generate private key private_key = secrets.randbits(256) private_key_hex = hex(private_key)[2:].zfill(64) # Generate address using Web3 w3 = Web3() account = w3.eth.account.from_key(private_key_hex) return private_key_hex, account.address @staticmethod def sign_transaction(private_key_hex: str, transaction_data: Dict) -> str: w3 = Web3() # Sign the transaction signed_txn = w3.eth.account.sign_transaction(transaction_data, private_key_hex) return signed_txn.rawTransaction.hex() @staticmethod def verify_address(address: str) -> bool: try: return Web3.is_address(address) except Exception: return False class WalletFactory: @staticmethod def create_wallet(currency: str) -> Tuple[str, str]: currency = currency.upper() if currency == 'BTC': return BitcoinWallet.generate_wallet() elif currency in ['ETH', 'USDT']: return EthereumWallet.generate_wallet() else: raise ValueError(f"Unsupported currency: {currency}") @staticmethod def sign_transaction(currency: str, private_key: str, transaction_data: Dict) -> str: currency = currency.upper() if currency == 'BTC': return BitcoinWallet.sign_transaction(private_key, transaction_data) elif currency in ['ETH', 'USDT']: return EthereumWallet.sign_transaction(private_key, transaction_data) else: raise ValueError(f"Unsupported currency: {currency}") @staticmethod def verify_address(currency: str, address: str) -> bool: currency = currency.upper() if currency == 'BTC': return BitcoinWallet.verify_address(address) elif currency in ['ETH', 'USDT']: return EthereumWallet.verify_address(address) else: return False