问题现象描述
当开发者使用pycryptodome库的AES.new()方法时,经常会遇到"ValueError: Incorrect AES key length"错误。这个错误表明传入的加密密钥不符合AES算法的长度要求。典型错误场景如下:
from Crypto.Cipher import AES
key = b'my_short_key' # 只有11字节
cipher = AES.new(key, AES.MODE_CBC) # 触发错误
错误原因深度分析
AES(Advanced Encryption Standard)作为对称加密算法,对密钥长度有严格规定:
- 128位(16字节):AES-128标准
- 192位(24字节):AES-192标准
- 256位(32字节):AES-256标准
常见触发错误的操作包括:
- 直接使用用户输入的原始字符串作为密钥
- 未对密码进行适当的哈希处理
- 混淆了密钥和初始化向量(IV)的长度要求
完整解决方案
方法一:使用固定长度密钥
最直接的解决方案是确保密钥长度符合标准:
key = b'16_bytes_long_key!' # 精确16字节
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
方法二:密钥派生函数(KDF)
推荐使用PBKDF2或scrypt从可变长度密码生成固定长度密钥:
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Hash import SHA256
password = b'user_password'
salt = b'random_salt'
key = PBKDF2(password, salt, 16, count=100000, hmac_hash_module=SHA256)
方法三:哈希摘要法
使用哈希算法将任意长度输入转换为固定长度:
from Crypto.Hash import SHA256
def get_aes_key(password):
h = SHA256.new(password)
return h.digest()[:16] # 取前16字节作为AES-128密钥
最佳实践建议
- 始终使用密钥派生函数处理用户输入的密码
- 为每个加密操作生成随机盐值(salt)
- 考虑使用
Fernet等高层加密方案简化操作 - 在单元测试中加入密钥长度验证
扩展知识:相关参数要求
| 参数 | 长度要求 | 备注 |
|---|---|---|
| AES密钥 | 16/24/32字节 | 必须严格匹配 |
| 初始化向量(IV) | 16字节 | CBC模式必需 |
| Nonce | 7-13字节 | CTR模式使用 |
调试技巧
遇到密钥长度问题时:
- 使用
len(key)确认实际字节长度 - 检查字符串编码方式(UTF-8与ASCII可能产生不同长度)
- 验证二进制数据是否包含意外换行符