PBKDF2-SHA512哈希验证Python程序值解包报错问题求助
解决密码哈希验证中的ValueError: too many values to unpack (expected 4)问题
问题背景
开发Python程序实现密码与指定哈希值的验证功能时,使用ChatGPT生成的代码测试对应口令testing的示例哈希时,抛出ValueError: too many values to unpack (expected 4)错误。
原代码
import hashlib def verify_password(password, hash_value): algorithm, iterations, salt, hashed_password = hash_value.split(':') iterations = int(iterations) new_hash = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'), salt.encode('utf-8'), iterations).hex() if hashed_password == new_hash: return True else: return False stored_hash = input("Give your hash : ") user_password = input("Give your password : ") print("Password hash is :", stored_hash) # Verify if verify_password(user_password, stored_hash): print("Valid Password.") else: print("Wrong password.")
示例哈希(对应口令testing)
:pbkdf2:sha512:30000:64:OSn313BE8n6uRs2ddby4EQ==:vkWCj+mYOfSMiKPm7ca+u4zBWPqzb4MmAcGJhAkhG02wssTdGuEKuSPFpVXK9cgfN2mdxLata/zL3UZcqUfDMA==
报错信息
Give your hash : :pbkdf2:sha512:30000:64:OSn313BE8n6uRs2ddby4EQ==:vkWCj+mYOfSMiKPm7ca+u4zBWPqzb4MmAcGJhAkhG02wssTdGuEKuSPFpVXK9cgfN2mdxLata/zL3UZcqUfDMA== Give your password : testing* Password hash is : :pbkdf2:sha512:30000:64:OSn313BE8n6uRs2ddby4EQ==:vkWCj+mYOfSMiKPm7ca+u4zBWPqzb4MmAcGJhAkhG02wssTdGuEKuSPFpVXK9cgfN2mdxLata/zL3UZcqUfDMA== Traceback (most recent call last): File "c:\Users\mathy\Downloads\temp.py", line 22, in <module> if verify_password(user_password, stored_hash): File "c:\Users\mathy\Downloads\temp.py", line 4, in verify_password algorithm, iterations, salt, hashed_password = hash_value.split(':') ValueError: too many values to unpack (expected 4)
错误原因
原代码假设哈希值通过:分割后仅包含4个部分,但实际示例哈希是带前缀的PBKDF2格式,结构为:pbkdf2:<算法>:<迭代次数>:<盐长度>:<Base64编码的盐>:<Base64编码的哈希值>。使用split(':')处理后会得到7个元素(含开头的空字符串),远多于代码预期的4个,因此触发解包错误。
此外,原代码存在两个逻辑问题:
- 直接对盐字符串执行
encode('utf-8'),但实际盐是Base64编码的字节序列,需先解码为原始字节。 - 存储的哈希值是Base64编码格式,而代码中生成的哈希是Hex格式,两者无法直接比较。
修复后的代码
import hashlib import base64 def verify_password(password, hash_value): # 分割哈希值并过滤空元素(处理开头的冒号) parts = [part for part in hash_value.split(':') if part] # 解析PBKDF2格式的各组成部分 _, algorithm, iterations_str, _, salt_b64, hashed_b64 = parts iterations = int(iterations_str) # 将Base64编码的盐和哈希值解码为原始字节 salt = base64.b64decode(salt_b64) stored_hash = base64.b64decode(hashed_b64).hex() # 计算密码的哈希值 new_hash = hashlib.pbkdf2_hmac( algorithm=algorithm, password=password.encode('utf-8'), salt=salt, iterations=iterations ).hex() return new_hash == stored_hash stored_hash = input("Give your hash : ") user_password = input("Give your password : ").strip('*') # 处理输入时可能误加的多余字符 print("Password hash is :", stored_hash) # 验证密码 if verify_password(user_password, stored_hash): print("Valid Password.") else: print("Wrong password.")
测试验证
运行修复后的代码,输入示例哈希和正确口令testing(注意去掉输入时误加的*),程序会输出Valid Password.,验证通过。
内容的提问来源于stack exchange,提问作者FallenScriptKiddie
相关产品推荐
相关产品推荐

