You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyCrypto AES无法加密含č/š/ž等特殊字符的字符串问题求助

Fixing AES Encryption Errors with Special Characters (č, š, ž) in PyCrypto

Hey there! I’ve run into this exact issue before—special characters like č, š, ž break AES encryption in PyCrypto because of how string encoding works under the hood. Let’s break down the problem and fix it step by step.

The Root Cause

AES encryption (and most crypto libraries) operates on byte data, not raw strings. When you try to encrypt a string with non-ASCII characters using the default string-to-bytes conversion (like ASCII), those special characters can’t be represented in ASCII, leading to encoding errors or corrupted data.

The fix is straightforward: we need to use a Unicode-compatible encoding (like UTF-8) to convert our strings to bytes before encryption, then reverse the process when decrypting.

Step-by-Step Solution

1. Standardize on UTF-8 for String ↔ Byte Conversion

Always encode your name string to UTF-8 bytes before passing it to AES, and decode the decrypted bytes back to a UTF-8 string afterward. This ensures all special characters are preserved correctly across systems.

2. Handle AES Block Size Padding

AES requires input data to be a multiple of its block size (16 bytes for AES-128). We’ll use PKCS7 padding to handle this—PyCrypto provides helper functions for this in Crypto.Util.Padding.

3. Full Working Example

Here’s a complete, tested code snippet that handles special characters without errors:

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes

def encrypt_name(name: str, key: bytes) -> bytes:
    # Encode the name to UTF-8 bytes first
    name_bytes = name.encode('utf-8')
    # Generate a random initialization vector (IV) - required for CBC mode
    iv = get_random_bytes(AES.block_size)
    # Initialize AES cipher in CBC mode
    cipher = AES.new(key, AES.MODE_CBC, iv)
    # Pad the data to match AES block size, then encrypt
    encrypted_data = cipher.encrypt(pad(name_bytes, AES.block_size))
    # Return IV + encrypted data (we need the IV to decrypt later)
    return iv + encrypted_data

def decrypt_name(encrypted_data: bytes, key: bytes) -> str:
    # Split the IV from the encrypted content
    iv = encrypted_data[:AES.block_size]
    ciphertext = encrypted_data[AES.block_size:]
    # Initialize the cipher with the same key and IV
    cipher = AES.new(key, AES.MODE_CBC, iv)
    # Decrypt and remove padding, then decode back to a string
    decrypted_bytes = unpad(cipher.decrypt(ciphertext), AES.block_size)
    return decrypted_bytes.decode('utf-8')

# Test with a name containing special characters
if __name__ == "__main__":
    # Generate a secure 256-bit (32-byte) key
    secret_key = get_random_bytes(32)
    test_name = "Štrah"
    
    encrypted = encrypt_name(test_name, secret_key)
    decrypted = decrypt_name(encrypted, secret_key)
    
    print(f"Original name: {test_name}")
    print(f"Encrypted data (hex): {encrypted.hex()}")
    print(f"Decrypted name: {decrypted}")
    print(f"Names match: {test_name == decrypted}")  # Should print True

Key Tips

  • Never skip the IV: The initialization vector ensures identical plaintexts encrypt to different ciphertexts. Always generate a new random IV for each encryption, and store it alongside the ciphertext (we prepend it here for convenience).
  • Use a secure key: Generate your key with get_random_bytes() instead of hardcoding a string—this avoids weak keys that are easy to guess.
  • Stick to UTF-8: It’s the universal standard for Unicode characters, so you won’t run into issues with other special characters down the line.

This should resolve the errors you’re seeing with names containing č, š, ž, or any other Unicode character.

内容的提问来源于stack exchange,提问作者Razmooo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:40:34