1. 问题现象与背景
在使用Python的pycryptodome库进行AES加密时,开发者常会遇到ValueError: Incorrect AES key length (X bytes)错误。该错误通常出现在以下场景:
- 直接使用用户输入的原始字符串作为密钥
- 未对密钥进行长度标准化处理
- 混淆了AES-128、AES-192和AES-256的密钥要求
2. 错误根源分析
AES算法严格规定密钥长度必须是16字节(128位)、24字节(192位)或32字节(256位)。当出现此错误时,说明:
# 典型错误示例
from Crypto.Cipher import AES
key = "my_weak_key" # 仅11字节
cipher = AES.new(key, AES.MODE_CBC) # 触发错误
3. 解决方案与代码实现
3.1 密钥标准化方法
推荐使用PBKDF2或Scrypt算法派生符合长度的密钥:
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Hash import SHA512
salt = b"random_salt"
key = PBKDF2("password", salt, 32, count=1000000, hmac_hash_module=SHA512)
# 生成32字节(256位)AES密钥
3.2 动态长度适配方案
通过哈希函数自动适配密钥长度:
import hashlib
def adjust_key(key_str):
hash_obj = hashlib.sha256(key_str.encode())
return hash_obj.digest() # 固定32字节输出
4. 最佳实践建议
- 始终使用密钥派生函数(KDF)而非原始字符串
- 为不同安全级别选择适当密钥长度:
AES类型 密钥长度 推荐场景 AES-128 16字节 一般数据加密 AES-256 32字节 金融/医疗数据 - 结合HMAC实现加密+完整性验证
5. 高级应用:多因素密钥生成
对于高安全需求场景,建议采用组合密钥技术:
import os
from Crypto.Protocol.KDF import scrypt
part1 = os.urandom(16)
part2 = b"static_secret"
master_key = scrypt(part1 + part2, salt=None, key_len=32, N=2**20, r=8, p=1)