Web Python 加密安全示例

Web Python 加密和安全示例,包括哈希计算、对称加密和 Base64 编码

💻 哈希计算 python

🟢 simple ⭐⭐

使用 hashlib 模块计算各种哈希值,包括 MD5、SHA1、SHA256、SHA512、HMAC 和盐值哈希

⏱️ 25 min 🏷️ python, web, cryptography, hash
Prerequisites: Basic Python, hashlib module
# Web Python Hash Computation Examples
# Computing various hash values using hashlib module

# 1. Basic Hash Functions
import hashlib
import hmac
import os
from typing import Optional, Union

def compute_md5(data: Union[str, bytes]) -> str:
    """
    Compute MD5 hash

    Args:
        data: Input data (string or bytes)

    Returns:
        Hexadecimal MD5 hash
    """
    if isinstance(data, str):
        data = data.encode('utf-8')
    return hashlib.md5(data).hexdigest()

def compute_sha1(data: Union[str, bytes]) -> str:
    """
    Compute SHA1 hash

    Args:
        data: Input data (string or bytes)

    Returns:
        Hexadecimal SHA1 hash
    """
    if isinstance(data, str):
        data = data.encode('utf-8')
    return hashlib.sha1(data).hexdigest()

def compute_sha256(data: Union[str, bytes]) -> str:
    """
    Compute SHA256 hash

    Args:
        data: Input data (string or bytes)

    Returns:
        Hexadecimal SHA256 hash
    """
    if isinstance(data, str):
        data = data.encode('utf-8')
    return hashlib.sha256(data).hexdigest()

def compute_sha512(data: Union[str, bytes]) -> str:
    """
    Compute SHA512 hash

    Args:
        data: Input data (string or bytes)

    Returns:
        Hexadecimal SHA512 hash
    """
    if isinstance(data, str):
        data = data.encode('utf-8')
    return hashlib.sha512(data).hexdigest()

def compute_sha3_256(data: Union[str, bytes]) -> str:
    """
    Compute SHA3-256 hash

    Args:
        data: Input data (string or bytes)

    Returns:
        Hexadecimal SHA3-256 hash
    """
    if isinstance(data, str):
        data = data.encode('utf-8')
    return hashlib.sha3_256(data).hexdigest()

def compute_blake2b(data: Union[str, bytes]) -> str:
    """
    Compute BLAKE2b hash

    Args:
        data: Input data (string or bytes)

    Returns:
        Hexadecimal BLAKE2b hash
    """
    if isinstance(data, str):
        data = data.encode('utf-8')
    return hashlib.blake2b(data).hexdigest()

# 2. File Hashing
def compute_file_hash(filepath: str, algorithm: str = 'sha256') -> Optional[str]:
    """
    Compute hash of a file

    Args:
        filepath: Path to file
        algorithm: Hash algorithm ('md5', 'sha1', 'sha256', 'sha512')

    Returns:
        Hexadecimal hash or None if error
    """
    hash_func = hashlib.new(algorithm)

    try:
        with open(filepath, 'rb') as f:
            for chunk in iter(lambda: f.read(4096), b''):
                hash_func.update(chunk)
        return hash_func.hexdigest()
    except FileNotFoundError:
        return None

def compute_file_md5(filepath: str) -> Optional[str]:
    """Compute MD5 hash of file"""
    return compute_file_hash(filepath, 'md5')

def compute_file_sha256(filepath: str) -> Optional[str]:
    """Compute SHA256 hash of file"""
    return compute_file_hash(filepath, 'sha256')

def compute_file_sha512(filepath: str) -> Optional[str]:
    """Compute SHA512 hash of file"""
    return compute_file_hash(filepath, 'sha512')

# 3. HMAC Computation
def compute_hmac_md5(key: Union[str, bytes], message: Union[str, bytes]) -> str:
    """
    Compute HMAC-MD5

    Args:
        key: Secret key
        message: Message to authenticate

    Returns:
        Hexadecimal HMAC
    """
    if isinstance(key, str):
        key = key.encode('utf-8')
    if isinstance(message, str):
        message = message.encode('utf-8')
    return hmac.new(key, message, hashlib.md5).hexdigest()

def compute_hmac_sha1(key: Union[str, bytes], message: Union[str, bytes]) -> str:
    """
    Compute HMAC-SHA1

    Args:
        key: Secret key
        message: Message to authenticate

    Returns:
        Hexadecimal HMAC
    """
    if isinstance(key, str):
        key = key.encode('utf-8')
    if isinstance(message, str):
        message = message.encode('utf-8')
    return hmac.new(key, message, hashlib.sha1).hexdigest()

def compute_hmac_sha256(key: Union[str, bytes], message: Union[str, bytes]) -> str:
    """
    Compute HMAC-SHA256

    Args:
        key: Secret key
        message: Message to authenticate

    Returns:
        Hexadecimal HMAC
    """
    if isinstance(key, str):
        key = key.encode('utf-8')
    if isinstance(message, str):
        message = message.encode('utf-8')
    return hmac.new(key, message, hashlib.sha256).hexdigest()

def compute_hmac_sha512(key: Union[str, bytes], message: Union[str, bytes]) -> str:
    """
    Compute HMAC-SHA512

    Args:
        key: Secret key
        message: Message to authenticate

    Returns:
        Hexadecimal HMAC
    """
    if isinstance(key, str):
        key = key.encode('utf-8')
    if isinstance(message, str):
        message = message.encode('utf-8')
    return hmac.new(key, message, hashlib.sha512).hexdigest()

# 4. Hash Comparison
def compare_hash(hash1: str, hash2: str) -> bool:
    """
    Compare two hashes securely

    Args:
        hash1: First hash
        hash2: Second hash

    Returns:
        True if equal
    """
    return hmac.compare_digest(hash1, hash2)

def verify_hash(data: Union[str, bytes], expected_hash: str, algorithm: str = 'sha256') -> bool:
    """
    Verify data against expected hash

    Args:
        data: Input data
        expected_hash: Expected hash value
        algorithm: Hash algorithm

    Returns:
        True if matches
    """
    if isinstance(data, str):
        data = data.encode('utf-8')

    hash_func = hashlib.new(algorithm, data)
    computed_hash = hash_func.hexdigest()
    return compare_hash(computed_hash, expected_hash)

def verify_file_hash(filepath: str, expected_hash: str, algorithm: str = 'sha256') -> bool:
    """
    Verify file hash

    Args:
        filepath: Path to file
        expected_hash: Expected hash value
        algorithm: Hash algorithm

    Returns:
        True if matches
    """
    computed_hash = compute_file_hash(filepath, algorithm)
    return compare_hash(computed_hash, expected_hash) if computed_hash else False

# 5. Salted Hashing
def generate_salt(length: int = 32) -> bytes:
    """
    Generate random salt

    Args:
        length: Salt length in bytes

    Returns:
        Random salt bytes
    """
    return os.urandom(length)

def compute_salted_hash(data: Union[str, bytes], salt: Optional[bytes] = None, algorithm: str = 'sha256') -> tuple:
    """
    Compute salted hash

    Args:
        data: Input data
        salt: Salt (auto-generated if None)
        algorithm: Hash algorithm

    Returns:
        (salt, hash) tuple
    """
    if isinstance(data, str):
        data = data.encode('utf-8')

    if salt is None:
        salt = generate_salt()

    hash_func = hashlib.new(algorithm)
    hash_func.update(salt + data)
    return salt, hash_func.hexdigest()

def verify_salted_hash(data: Union[str, bytes], salt: bytes, expected_hash: str, algorithm: str = 'sha256') -> bool:
    """
    Verify salted hash

    Args:
        data: Input data
        salt: Salt used
        expected_hash: Expected hash
        algorithm: Hash algorithm

    Returns:
        True if matches
    """
    if isinstance(data, str):
        data = data.encode('utf-8')

    hash_func = hashlib.new(algorithm)
    hash_func.update(salt + data)
    computed_hash = hash_func.hexdigest()
    return compare_hash(computed_hash, expected_hash)

# 6. Multiple Hashes
def compute_all_hashes(data: Union[str, bytes]) -> dict:
    """
    Compute multiple hashes of data

    Args:
        data: Input data

    Returns:
        Dictionary with all hashes
    """
    if isinstance(data, str):
        data = data.encode('utf-8')

    return {
        'md5': hashlib.md5(data).hexdigest(),
        'sha1': hashlib.sha1(data).hexdigest(),
        'sha256': hashlib.sha256(data).hexdigest(),
        'sha512': hashlib.sha512(data).hexdigest(),
        'sha3_256': hashlib.sha3_256(data).hexdigest(),
        'blake2b': hashlib.blake2b(data).hexdigest()
    }

# 7. Hash-based Data Integrity
def create_checksum(data: Union[str, bytes]) -> str:
    """
    Create checksum for data

    Args:
        data: Input data

    Returns:
        Checksum hash
    """
    return compute_sha256(data)

def verify_checksum(data: Union[str, bytes], checksum: str) -> bool:
    """
    Verify data checksum

    Args:
        data: Input data
        checksum: Expected checksum

    Returns:
        True if valid
    """
    return verify_hash(data, checksum, 'sha256')

def create_file_checksum(filepath: str) -> Optional[str]:
    """
    Create checksum for file

    Args:
        filepath: Path to file

    Returns:
        Checksum hash or None
    """
    return compute_file_sha256(filepath)

# 8. Progressive Hashing
def hash_multiple_chunks(chunks: list) -> str:
    """
    Hash multiple data chunks

    Args:
        chunks: List of data chunks

    Returns:
        Combined hash
    """
    hash_func = hashlib.sha256()
    for chunk in chunks:
        if isinstance(chunk, str):
            chunk = chunk.encode('utf-8')
        hash_func.update(chunk)
    return hash_func.hexdigest()

# Usage Examples
def demonstrate_hash_computation():
    print("=== Web Python Hash Computation Examples ===\n")

    # 1. Basic hashes
    print("--- 1. Basic Hash Functions ---")
    data = "Hello, World!"
    print(f"Data: {data}")
    print(f"MD5: {compute_md5(data)}")
    print(f"SHA1: {compute_sha1(data)}")
    print(f"SHA256: {compute_sha256(data)}")
    print(f"SHA512: {compute_sha512(data)}")
    print(f"SHA3-256: {compute_sha3_256(data)}")
    print(f"BLAKE2b: {compute_blake2b(data)}")

    # 2. All hashes
    print("\n--- 2. Compute All Hashes ---")
    all_hashes = compute_all_hashes("Python Cryptography")
    print("All hashes:")
    for name, hash_value in all_hashes.items():
        print(f"  {name}: {hash_value}")

    # 3. HMAC
    print("\n--- 3. HMAC Computation ---")
    key = "secret_key"
    message = "authenticated message"
    print(f"Key: {key}")
    print(f"Message: {message}")
    print(f"HMAC-SHA256: {compute_hmac_sha256(key, message)}")
    print(f"HMAC-SHA512: {compute_hmac_sha512(key, message)}")

    # 4. Hash comparison
    print("\n--- 4. Hash Comparison ---")
    hash1 = compute_sha256("data1")
    hash2 = compute_sha256("data2")
    hash3 = compute_sha256("data1")
    print(f"Hash1 == Hash2: {compare_hash(hash1, hash2)}")
    print(f"Hash1 == Hash3: {compare_hash(hash1, hash3)}")

    # 5. Salted hashing
    print("\n--- 5. Salted Hashing ---")
    password = "secure_password"
    salt, hash_value = compute_salted_hash(password)
    print(f"Password: {password}")
    print(f"Salt: {salt.hex()}")
    print(f"Hash: {hash_value}")
    print(f"Verified: {verify_salted_hash(password, salt, hash_value)}")

    # 6. Checksum
    print("\n--- 6. Data Integrity Checksum ---")
    data = "important data"
    checksum = create_checksum(data)
    print(f"Data: {data}")
    print(f"Checksum: {checksum}")
    print(f"Verified: {verify_checksum(data, checksum)}")

    # 7. Progressive hashing
    print("\n--- 7. Progressive Hashing ---")
    chunks = ["chunk1", "chunk2", "chunk3"]
    combined_hash = hash_multiple_chunks(chunks)
    print(f"Chunks: {chunks}")
    print(f"Combined hash: {combined_hash}")

    print("\n=== All Hash Computation Examples Completed ===")

# Export functions
export { compute_md5, compute_sha1, compute_sha256, compute_sha512 }
export { compute_sha3_256, compute_blake2b }
export { compute_file_hash, compute_file_md5, compute_file_sha256, compute_file_sha512 }
export { compute_hmac_md5, compute_hmac_sha1, compute_hmac_sha256, compute_hmac_sha512 }
export { compare_hash, verify_hash, verify_file_hash }
export { generate_salt, compute_salted_hash, verify_salted_hash }
export { compute_all_hashes }
export { create_checksum, verify_checksum, create_file_checksum }
export { hash_multiple_chunks }
export { demonstrate_hash_computation }

💻 Base64 编码 python

🟢 simple ⭐⭐

使用 Base64 编码和解码数据,支持 URL 安全变体、文件支持和十六进制转换

⏱️ 20 min 🏷️ python, web, cryptography, encoding
Prerequisites: Basic Python, base64 module
# Web Python Base64 Encoding Examples
# Base64 encoding/decoding with various formats

# 1. Basic Base64 Encoding/Decoding
import base64
from typing import Union

def encode_base64(data: Union[str, bytes]) -> bytes:
    """
    Encode data to Base64

    Args:
        data: Input data (string or bytes)

    Returns:
        Base64 encoded bytes
    """
    if isinstance(data, str):
        data = data.encode('utf-8')
    return base64.b64encode(data)

def decode_base64(encoded: Union[bytes, str]) -> bytes:
    """
    Decode Base64 data

    Args:
        encoded: Base64 encoded data

    Returns:
        Decoded bytes

    Raises:
        Error: If invalid Base64
    """
    if isinstance(encoded, str):
        encoded = encoded.encode('utf-8')
    return base64.b64decode(encoded)

def encode_base64_string(data: Union[str, bytes]) -> str:
    """
    Encode data to Base64 string

    Args:
        data: Input data

    Returns:
        Base64 encoded string
    """
    return encode_base64(data).decode('utf-8')

def decode_base64_string(encoded: str) -> str:
    """
    Decode Base64 string to string

    Args:
        encoded: Base64 encoded string

    Returns:
        Decoded string
    """
    return decode_base64(encoded).decode('utf-8')

# 2. URL-Safe Base64
def encode_base64_url(data: Union[str, bytes]) -> bytes:
    """
    Encode to URL-safe Base64

    Args:
        data: Input data

    Returns:
        URL-safe Base64 bytes
    """
    if isinstance(data, str):
        data = data.encode('utf-8')
    return base64.urlsafe_b64encode(data)

def decode_base64_url(encoded: Union[bytes, str]) -> bytes:
    """
    Decode URL-safe Base64

    Args:
        encoded: URL-safe Base64 data

    Returns:
        Decoded bytes
    """
    if isinstance(encoded, str):
        encoded = encoded.encode('utf-8')
    return base64.urlsafe_b64decode(encoded)

def encode_base64_url_string(data: Union[str, bytes]) -> str:
    """
    Encode to URL-safe Base64 string

    Args:
        data: Input data

    Returns:
        URL-safe Base64 string
    """
    return encode_base64_url(data).decode('utf-8')

def decode_base64_url_string(encoded: str) -> str:
    """
    Decode URL-safe Base64 string

    Args:
        encoded: URL-safe Base64 string

    Returns:
        Decoded string
    """
    return decode_base64_url(encoded).decode('utf-8')

# 3. Base64 with Padding Control
def encode_base64_no_padding(data: Union[str, bytes]) -> str:
    """
    Encode to Base64 without padding

    Args:
        data: Input data

    Returns:
        Base64 string without '=' padding
    """
    encoded = encode_base64_string(data)
    return encoded.rstrip('=')

def decode_base64_no_padding(encoded: str) -> bytes:
    """
    Decode Base64 without padding

    Args:
        encoded: Base64 string without padding

    Returns:
        Decoded bytes
    """
    # Add padding if necessary
    padding = len(encoded) % 4
    if padding:
        encoded += '=' * (4 - padding)
    return decode_base64(encoded)

# 4. Hex to Base64 Conversion
def hex_to_base64(hex_string: str) -> str:
    """
    Convert hex string to Base64

    Args:
        hex_string: Hexadecimal string

    Returns:
        Base64 encoded string
    """
    bytes_data = bytes.fromhex(hex_string)
    return encode_base64_string(bytes_data)

def base64_to_hex(encoded: str) -> str:
    """
    Convert Base64 to hex string

    Args:
        encoded: Base64 encoded string

    Returns:
        Hexadecimal string
    """
    bytes_data = decode_base64(encoded)
    return bytes_data.hex()

# 5. File Base64 Encoding
def encode_file_base64(filepath: str) -> str:
    """
    Encode file to Base64 string

    Args:
        filepath: Path to file

    Returns:
        Base64 encoded string
    """
    with open(filepath, 'rb') as f:
        file_data = f.read()
    return encode_base64_string(file_data)

def decode_base64_to_file(encoded: str, filepath: str) -> None:
    """
    Decode Base64 string to file

    Args:
        encoded: Base64 encoded string
        filepath: Output file path
    """
    file_data = decode_base64(encoded)
    with open(filepath, 'wb') as f:
        f.write(file_data)

def encode_file_base64_chunked(filepath: str, chunk_size: int = 8192) -> str:
    """
    Encode large file to Base64 in chunks

    Args:
        filepath: Path to file
        chunk_size: Chunk size for processing

    Returns:
        Base64 encoded string
    """
    import base64
    encoded_chunks = []

    with open(filepath, 'rb') as f:
        while True:
            chunk = f.read(chunk_size)
            if not chunk:
                break
            encoded_chunks.append(base64.b64encode(chunk))

    return b''.join(encoded_chunks).decode('utf-8')

# 6. Base64 Variants
def encode_base64_standard(data: Union[str, bytes]) -> str:
    """Standard Base64 encoding with padding"""
    return encode_base64_string(data)

def encode_base64_url_safe(data: Union[str, bytes]) -> str:
    """URL-safe Base64 encoding"""
    return encode_base64_url_string(data).rstrip('=')

def encode_base64_mime(data: Union[str, bytes], line_length: int = 76) -> str:
    """
    MIME-compatible Base64 encoding with line breaks

    Args:
        data: Input data
        line_length: Maximum line length

    Returns:
        MIME-formatted Base64 string
    """
    encoded = encode_base64_string(data)
    lines = [encoded[i:i+line_length] for i in range(0, len(encoded), line_length)]
    return '\n'.join(lines)

# 7. Validation
def is_valid_base64(encoded: str) -> bool:
    """
    Check if string is valid Base64

    Args:
        encoded: String to validate

    Returns:
        True if valid Base64
    """
    import re
    pattern = r'^[A-Za-z0-9+/]*={0,2}$'
    return bool(re.match(pattern, encoded))

def is_valid_base64_url(encoded: str) -> bool:
    """
    Check if string is valid URL-safe Base64

    Args:
        encoded: String to validate

    Returns:
        True if valid URL-safe Base64
    """
    import re
    pattern = r'^[A-Za-z0-9_-]*={0,2}$'
    return bool(re.match(pattern, encoded))

# 8. Utility Functions
def get_base64_length(original_length: int) -> int:
    """
    Calculate Base64 encoded length

    Args:
        original_length: Original data length in bytes

    Returns:
        Base64 encoded length (with padding)
    """
    return ((original_length + 2) // 3) * 4

def safe_base64_encode(data: Union[str, bytes]) -> str:
    """
    Safely encode to Base64 (handles errors)

    Args:
        data: Input data

    Returns:
        Base64 string or empty string on error
    """
    try:
        return encode_base64_string(data)
    except Exception:
        return ""

def safe_base64_decode(encoded: str) -> bytes:
    """
    Safely decode Base64 (handles errors)

    Args:
        encoded: Base64 string

    Returns:
        Decoded bytes or empty bytes on error
    """
    try:
        return decode_base64(encoded)
    except Exception:
        return b''

# 9. Advanced Operations
def encode_base64_with_prefix(data: Union[str, bytes], prefix: str = 'data:') -> str:
    """
    Encode with data URI prefix

    Args:
        data: Input data
        prefix: URI prefix

    Returns:
        Data URI string
    """
    encoded = encode_base64_string(data)
    return f"{prefix};base64,{encoded}"

def decode_base64_from_uri(uri: str) -> bytes:
    """
    Decode Base64 from data URI

    Args:
        uri: Data URI string

    Returns:
        Decoded bytes
    """
    # Extract Base64 part
    if ',' in uri:
        encoded = uri.split(',', 1)[1]
        return decode_base64(encoded)
    return b''

def compare_base64_data(data1: Union[str, bytes], data2: Union[str, bytes]) -> bool:
    """
    Compare two data via Base64 encoding

    Args:
        data1: First data
        data2: Second data

    Returns:
        True if Base64 encoded values match
    """
    return encode_base64_string(data1) == encode_base64_string(data2)

# Usage Examples
def demonstrate_base64_encoding():
    print("=== Web Python Base64 Encoding Examples ===\n")

    # 1. Basic encoding
    print("--- 1. Basic Base64 Encoding ---")
    data = "Hello, World!"
    encoded = encode_base64_string(data)
    decoded = decode_base64_string(encoded)
    print(f"Original: {data}")
    print(f"Encoded: {encoded}")
    print(f"Decoded: {decoded}")
    print(f"Match: {data == decoded}")

    # 2. Bytes encoding
    print("\n--- 2. Bytes Encoding ---")
    bytes_data = b"Binary data \x00\x01\x02"
    encoded = encode_base64_string(bytes_data)
    print(f"Original bytes: {bytes_data}")
    print(f"Encoded: {encoded}")

    # 3. URL-safe encoding
    print("\n--- 3. URL-Safe Base64 ---")
    data = "[email protected]?param=value"
    standard = encode_base64_string(data)
    url_safe = encode_base64_url_string(data)
    print(f"Original: {data}")
    print(f"Standard: {standard}")
    print(f"URL-safe: {url_safe}")
    print(f"URL decoded: {decode_base64_url_string(url_safe)}")

    # 4. No padding
    print("\n--- 4. Base64 Without Padding ---")
    data = "Test"
    with_padding = encode_base64_string(data)
    without_padding = encode_base64_no_padding(data)
    print(f"Original: {data}")
    print(f"With padding: {with_padding}")
    print(f"Without padding: {without_padding}")
    print(f"Both decode correctly: {decode_base64_string(with_padding) == decode_base64_no_padding(without_padding)}")

    # 5. Hex conversion
    print("\n--- 5. Hex <-> Base64 Conversion ---")
    hex_data = "48656c6c6f"  # "Hello" in hex
    b64_from_hex = hex_to_base64(hex_data)
    hex_from_b64 = base64_to_hex(b64_from_hex)
    print(f"Hex: {hex_data}")
    print(f"Base64: {b64_from_hex}")
    print(f"Back to hex: {hex_from_b64}")
    print(f"Match: {hex_data == hex_from_b64}")

    # 6. MIME format
    print("\n--- 6. MIME-Compatible Encoding ---")
    data = "This is a longer string that will be split into multiple lines for MIME compatibility"
    mime_encoded = encode_base64_mime(data, line_length=20)
    print(f"Original: {data}")
    print(f"MIME encoded:\n{mime_encoded}")

    # 7. Validation
    print("\n--- 7. Base64 Validation ---")
    valid_b64 = "SGVsbG8sIFdvcmxkIQ=="
    invalid_b64 = "Hello@World!"
    print(f"'{valid_b64}' is valid: {is_valid_base64(valid_b64)}")
    print(f"'{invalid_b64}' is valid: {is_valid_base64(invalid_b64)}")

    # 8. Data URI
    print("\n--- 8. Data URI Encoding ---")
    data = "Sample text content"
    uri = encode_base64_with_prefix(data, prefix="data:text/plain")
    print(f"Data URI: {uri[:50]}...")
    decoded_from_uri = decode_base64_from_uri(uri).decode('utf-8')
    print(f"Decoded from URI: {decoded_from_uri}")
    print(f"Match: {data == decoded_from_uri}")

    # 9. Length calculation
    print("\n--- 9. Base64 Length Calculation ---")
    data = "A" * 10
    encoded = encode_base64_string(data)
    expected_length = get_base64_length(len(data))
    print(f"Original length: {len(data)} bytes")
    print(f"Encoded length: {len(encoded)} chars")
    print(f"Expected length: {expected_length} chars")
    print(f"Match: {len(encoded) == expected_length}")

    # 10. Safe operations
    print("\n--- 10. Safe Encoding/Decoding ---")
    print(f"Safe encode: {safe_base64_encode('Safe data')}")
    print(f"Safe decode valid: {safe_base64_decode('SGVsbG8=')}")
    print(f"Safe decode invalid: {safe_base64_decode('Invalid!')}")

    print("\n=== All Base64 Encoding Examples Completed ===")

# Export functions
export { encode_base64, decode_base64 }
export { encode_base64_string, decode_base64_string }
export { encode_base64_url, decode_base64_url }
export { encode_base64_url_string, decode_base64_url_string }
export { encode_base64_no_padding, decode_base64_no_padding }
export { hex_to_base64, base64_to_hex }
export { encode_file_base64, decode_base64_to_file, encode_file_base64_chunked }
export { encode_base64_standard, encode_base64_url_safe, encode_base64_mime }
export { is_valid_base64, is_valid_base64_url }
export { get_base64_length, safe_base64_encode, safe_base64_decode }
export { encode_base64_with_prefix, decode_base64_from_uri, compare_base64_data }
export { demonstrate_base64_encoding }

💻 对称加密 python

🟡 intermediate ⭐⭐⭐

使用 cryptography 库实现 AES 对称加密/解密,支持多种模式(CBC、GCM)

⏱️ 35 min 🏷️ python, web, cryptography, encryption
Prerequisites: Intermediate Python, cryptography library, security concepts
# Web Python Symmetric Encryption Examples
# AES encryption/decryption using cryptography library

# 1. Key Generation
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2
from cryptography.hazmat.backends import default_backend
import os
import secrets
from typing import Tuple, Union

def generate_random_key(key_size: int = 32) -> bytes:
    """
    Generate random encryption key

    Args:
        key_size: Key size in bytes (16=AES-128, 24=AES-192, 32=AES-256)

    Returns:
        Random key bytes
    """
    return secrets.token_bytes(key_size)

def generate_key_from_password(password: Union[str, bytes], salt: Optional[bytes] = None, iterations: int = 100000) -> Tuple[bytes, bytes]:
    """
    Derive encryption key from password using PBKDF2

    Args:
        password: User password
        salt: Salt (generated if None)
        iterations: PBKDF2 iterations

    Returns:
        (key, salt) tuple
    """
    if isinstance(password, str):
        password = password.encode('utf-8')

    if salt is None:
        salt = secrets.token_bytes(16)

    kdf = PBKDF2(
        algorithm=hashes.SHA256(),
        length=32,
        salt=salt,
        iterations=iterations,
        backend=default_backend()
    )
    key = kdf.derive(password)
    return key, salt

# 2. IV/Nonce Generation
def generate_iv(block_size: int = 16) -> bytes:
    """
    Generate initialization vector

    Args:
        block_size: Block size in bytes

    Returns:
        Random IV bytes
    """
    return secrets.token_bytes(block_size)

def generate_nonce(size: int = 12) -> bytes:
    """
    Generate nonce for GCM mode

    Args:
        size: Nonce size in bytes

    Returns:
        Random nonce bytes
    """
    return secrets.token_bytes(size)

# 3. AES-256-CBC Encryption/Decryption
def encrypt_aes_cbc(plaintext: Union[str, bytes], key: bytes, iv: Optional[bytes] = None) -> Tuple[bytes, bytes]:
    """
    Encrypt using AES-256-CBC

    Args:
        plaintext: Data to encrypt
        key: Encryption key (32 bytes for AES-256)
        iv: Initialization vector (generated if None)

    Returns:
        (ciphertext, iv) tuple
    """
    if isinstance(plaintext, str):
        plaintext = plaintext.encode('utf-8')

    # Pad plaintext to block size
    pad_length = 16 - (len(plaintext) % 16)
    plaintext = plaintext + bytes([pad_length] * pad_length)

    if iv is None:
        iv = generate_iv()

    cipher = Cipher(
        algorithms.AES(key),
        modes.CBC(iv),
        backend=default_backend()
    )
    encryptor = cipher.encryptor()
    ciphertext = encryptor.update(plaintext) + encryptor.finalize()

    return ciphertext, iv

def decrypt_aes_cbc(ciphertext: bytes, key: bytes, iv: bytes) -> bytes:
    """
    Decrypt AES-256-CBC ciphertext

    Args:
        ciphertext: Data to decrypt
        key: Decryption key
        iv: Initialization vector

    Returns:
        Decrypted plaintext
    """
    cipher = Cipher(
        algorithms.AES(key),
        modes.CBC(iv),
        backend=default_backend()
    )
    decryptor = cipher.decryptor()
    padded_plaintext = decryptor.update(ciphertext) + decryptor.finalize()

    # Remove padding
    pad_length = padded_plaintext[-1]
    plaintext = padded_plaintext[:-pad_length]

    return plaintext

# 4. AES-256-GCM Encryption/Decryption (Authenticated)
def encrypt_aes_gcm(plaintext: Union[str, bytes], key: bytes, nonce: Optional[bytes] = None, associated_data: Optional[bytes] = None) -> Tuple[bytes, bytes, bytes]:
    """
    Encrypt using AES-256-GCM with authentication

    Args:
        plaintext: Data to encrypt
        key: Encryption key (32 bytes for AES-256)
        nonce: Nonce (generated if None)
        associated_data: Additional authenticated data

    Returns:
        (ciphertext, nonce, tag) tuple
    """
    if isinstance(plaintext, str):
        plaintext = plaintext.encode('utf-8')

    if nonce is None:
        nonce = generate_nonce()

    cipher = Cipher(
        algorithms.AES(key),
        modes.GCM(nonce),
        backend=default_backend()
    )
    encryptor = cipher.encryptor()

    if associated_data:
        if isinstance(associated_data, str):
            associated_data = associated_data.encode('utf-8')
        encryptor.authenticate_additional_data(associated_data)

    ciphertext = encryptor.update(plaintext) + encryptor.finalize()
    return ciphertext, nonce, encryptor.tag

def decrypt_aes_gcm(ciphertext: bytes, key: bytes, nonce: bytes, tag: bytes, associated_data: Optional[bytes] = None) -> bytes:
    """
    Decrypt AES-256-GCM ciphertext with authentication

    Args:
        ciphertext: Data to decrypt
        key: Decryption key
        nonce: Nonce used for encryption
        tag: Authentication tag
        associated_data: Additional authenticated data

    Returns:
        Decrypted plaintext

    Raises:
        InvalidTag: If authentication fails
    """
    cipher = Cipher(
        algorithms.AES(key),
        modes.GCM(nonce, tag),
        backend=default_backend()
    )
    decryptor = cipher.decryptor()

    if associated_data:
        if isinstance(associated_data, str):
            associated_data = associated_data.encode('utf-8')
        decryptor.authenticate_additional_data(associated_data)

    plaintext = decryptor.update(ciphertext) + decryptor.finalize()
    return plaintext

# 5. AES-128/192/256 Support
def encrypt_aes(plaintext: Union[str, bytes], key: bytes, mode: str = 'CBC') -> Tuple[bytes, bytes]:
    """
    Encrypt using AES with specified key size

    Args:
        plaintext: Data to encrypt
        key: Encryption key (16/24/32 bytes for AES-128/192/256)
        mode: Encryption mode ('CBC' or 'GCM')

    Returns:
        (ciphertext, iv/nonce) tuple
    """
    if mode == 'GCM':
        ciphertext, nonce, tag = encrypt_aes_gcm(plaintext, key)
        return ciphertext, nonce
    else:
        return encrypt_aes_cbc(plaintext, key)

def decrypt_aes(ciphertext: bytes, key: bytes, iv: bytes, mode: str = 'CBC', tag: Optional[bytes] = None) -> bytes:
    """
    Decrypt using AES with specified key size

    Args:
        ciphertext: Data to decrypt
        key: Decryption key
        iv: IV or nonce
        mode: Encryption mode ('CBC' or 'GCM')
        tag: Authentication tag (for GCM mode)

    Returns:
        Decrypted plaintext
    """
    if mode == 'GCM':
        return decrypt_aes_gcm(ciphertext, key, iv, tag)
    else:
        return decrypt_aes_cbc(ciphertext, key, iv)

# 6. File Encryption/Decryption
def encrypt_file(input_path: str, output_path: str, key: bytes) -> None:
    """
    Encrypt file using AES-256-CBC

    Args:
        input_path: Input file path
        output_path: Output file path
        key: Encryption key
    """
    with open(input_path, 'rb') as f_in:
        plaintext = f_in.read()

    ciphertext, iv = encrypt_aes_cbc(plaintext, key)

    with open(output_path, 'wb') as f_out:
        f_out.write(iv)
        f_out.write(ciphertext)

def decrypt_file(input_path: str, output_path: str, key: bytes) -> None:
    """
    Decrypt file using AES-256-CBC

    Args:
        input_path: Input file path
        output_path: Output file path
        key: Decryption key
    """
    with open(input_path, 'rb') as f_in:
        iv = f_in.read(16)
        ciphertext = f_in.read()

    plaintext = decrypt_aes_cbc(ciphertext, key, iv)

    with open(output_path, 'wb') as f_out:
        f_out.write(plaintext)

# 7. High-Level Encryption Functions
def encrypt_message(message: str, password: str, mode: str = 'GCM') -> dict:
    """
    Encrypt message with password

    Args:
        message: Message to encrypt
        password: User password
        mode: Encryption mode

    Returns:
        Dictionary with encrypted data
    """
    key, salt = generate_key_from_password(password)

    if mode == 'GCM':
        ciphertext, nonce, tag = encrypt_aes_gcm(message, key)
        return {
            'ciphertext': ciphertext.hex(),
            'nonce': nonce.hex(),
            'tag': tag.hex(),
            'salt': salt.hex(),
            'mode': 'GCM'
        }
    else:
        ciphertext, iv = encrypt_aes_cbc(message, key)
        return {
            'ciphertext': ciphertext.hex(),
            'iv': iv.hex(),
            'salt': salt.hex(),
            'mode': 'CBC'
        }

def decrypt_message(encrypted_data: dict, password: str) -> str:
    """
    Decrypt message with password

    Args:
        encrypted_data: Dictionary with encrypted data
        password: User password

    Returns:
        Decrypted message
    """
    salt = bytes.fromhex(encrypted_data['salt'])
    key, _ = generate_key_from_password(password, salt)

    mode = encrypted_data['mode']
    ciphertext = bytes.fromhex(encrypted_data['ciphertext'])

    if mode == 'GCM':
        nonce = bytes.fromhex(encrypted_data['nonce'])
        tag = bytes.fromhex(encrypted_data['tag'])
        plaintext = decrypt_aes_gcm(ciphertext, key, nonce, tag)
    else:
        iv = bytes.fromhex(encrypted_data['iv'])
        plaintext = decrypt_aes_cbc(ciphertext, key, iv)

    return plaintext.decode('utf-8')

# 8. Key Management
def save_key(key: bytes, filepath: str) -> None:
    """
    Save key to file

    Args:
        key: Key bytes
        filepath: Output file path
    """
    with open(filepath, 'wb') as f:
        f.write(key)

def load_key(filepath: str) -> bytes:
    """
    Load key from file

    Args:
        filepath: Key file path

    Returns:
        Key bytes
    """
    with open(filepath, 'rb') as f:
        return f.read()

# Usage Examples
def demonstrate_symmetric_encryption():
    print("=== Web Python Symmetric Encryption Examples ===\n")

    # 1. Key generation
    print("--- 1. Key Generation ---")
    key = generate_random_key(32)
    print(f"Random key (hex): {key.hex()}")
    print(f"Key size: {len(key)} bytes (AES-256)")

    password = "secure_password_123"
    derived_key, salt = generate_key_from_password(password)
    print(f"\nPassword: {password}")
    print(f"Derived key: {derived_key.hex()}")
    print(f"Salt: {salt.hex()}")

    # 2. AES-CBC encryption
    print("\n--- 2. AES-256-CBC Encryption ---")
    plaintext = "Secret message to encrypt"
    key = generate_random_key(32)
    ciphertext, iv = encrypt_aes_cbc(plaintext, key)
    print(f"Plaintext: {plaintext}")
    print(f"Ciphertext (hex): {ciphertext.hex()}")
    print(f"IV (hex): {iv.hex()}")

    decrypted = decrypt_aes_cbc(ciphertext, key, iv)
    print(f"Decrypted: {decrypted.decode('utf-8')}")
    print(f"Match: {plaintext == decrypted.decode('utf-8')}")

    # 3. AES-GCM encryption
    print("\n--- 3. AES-256-GCM Encryption (Authenticated) ---")
    plaintext = "Authenticated secret message"
    associated_data = "metadata"
    ciphertext, nonce, tag = encrypt_aes_gcm(plaintext, key, associated_data=associated_data)
    print(f"Plaintext: {plaintext}")
    print(f"Associated data: {associated_data}")
    print(f"Ciphertext (hex): {ciphertext.hex()}")
    print(f"Nonce (hex): {nonce.hex()}")
    print(f"Tag (hex): {tag.hex()}")

    decrypted = decrypt_aes_gcm(ciphertext, key, nonce, tag, associated_data)
    print(f"Decrypted: {decrypted.decode('utf-8')}")
    print(f"Match: {plaintext == decrypted.decode('utf-8')}")

    # 4. High-level password encryption
    print("\n--- 4. Password-Based Encryption ---")
    message = "Top secret data"
    password = "my_secure_pass"
    encrypted = encrypt_message(message, password, mode='GCM')
    print(f"Original: {message}")
    print(f"Encrypted data:")
    for k, v in encrypted.items():
        print(f"  {k}: {v}")

    decrypted = decrypt_message(encrypted, password)
    print(f"Decrypted: {decrypted}")
    print(f"Match: {message == decrypted}")

    # 5. Different key sizes
    print("\n--- 5. AES Key Sizes ---")
    for size, name in [(16, 'AES-128'), (24, 'AES-192'), (32, 'AES-256')]:
        key = generate_random_key(size)
        plaintext = f"Test with {name}"
        ciphertext, iv = encrypt_aes(plaintext, key, mode='CBC')
        decrypted = decrypt_aes(ciphertext, key, iv, mode='CBC')
        print(f"{name}: {plaintext} -> {decrypted.decode('utf-8')} (Match: {plaintext == decrypted.decode('utf-8')})")

    print("\n=== All Symmetric Encryption Examples Completed ===")

# Export functions
export { generate_random_key, generate_key_from_password }
export { generate_iv, generate_nonce }
export { encrypt_aes_cbc, decrypt_aes_cbc }
export { encrypt_aes_gcm, decrypt_aes_gcm }
export { encrypt_aes, decrypt_aes }
export { encrypt_file, decrypt_file }
export { encrypt_message, decrypt_message }
export { save_key, load_key }
export { demonstrate_symmetric_encryption }