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

指定hash_len=32后Argon2哈希仍超32字节?AES加密报错求助

问题原因与解决方案

核心问题:Base64编码导致长度膨胀

你指定的hash_len=32是二进制哈希值的长度,但PasswordHasher.hash()返回的是符合Argon2标准格式的字符串,其中的哈希部分是经过Base64编码后的结果。

Base64编码规则是每3个二进制字节转换为4个ASCII字符,32字节的二进制数据编码后会变成43个字符(计算方式:ceil(32 / 3) * 4 = 43),这就是你看到哈希长度为43的原因。直接用这个编码后的字符串作为AES密钥,自然会因为长度不符合要求报错。

解决步骤

方法1:从哈希字符串中提取并解码哈希部分

Argon2的哈希字符串格式为:$argon2id$v=19$m=xxx,t=xxx,p=xxx$<Base64编码的盐>$<Base64编码的哈希>

你可以按$分割字符串,提取最后一段(哈希的Base64编码),再解码为原始二进制字节:

import base64
from argon2 import PasswordHasher

ph = PasswordHasher(hash_len=32, salt_len=16)
hash_str = ph.hash(key)

# 分割哈希字符串,提取Base64编码的哈希部分
parts = hash_str.split('$')
b64_hash = parts[-1]
# 解码为32字节的二进制密钥
aes_key = base64.b64decode(b64_hash)

# 现在可以正常使用AES
from Crypto.Cipher import AES

cipher = AES.new(aes_key, AES.MODE_EAX)
nonce = cipher.nonce
ciphertext, tag = cipher.encrypt_and_digest(data)

方法2:使用Argon2低级API直接生成原始哈希

如果不需要用于密码验证,只是生成密钥,可以跳过PasswordHasher的格式化输出,直接用低级API生成二进制哈希:

from argon2.low_level import hash_secret_raw, Type
import os

# 生成16字节随机盐
salt = os.urandom(16)
# 生成32字节的二进制哈希
aes_key = hash_secret_raw(
    secret=key.encode('utf-8'),
    salt=salt,
    time_cost=3,
    memory_cost=65536,
    parallelism=4,
    hash_len=32,
    type=Type.ID
)

额外提醒

  • PasswordHasher的设计初衷是密码验证,它生成的带格式字符串包含了验证所需的所有参数(算法、迭代次数、内存占用等),所以如果之后需要验证密码,要保留完整的hash_str,不要只存解码后的密钥。
  • AES密钥必须是二进制字节,不能是字符串,所以一定要确保你传递给AES.new()的是解码后的字节数据,不是编码后的字符串。

内容的提问来源于stack exchange,提问作者Varun Pius Rodrigues

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 04:45:11