密码哈希算法输入相同数据却生成不同结果的排查求助
问题排查与修复方案
1. 数据库salt字段长度不足导致截断
你的randomsalt()函数生成的是256*3//4=192位的token_urlsafe字符串,如果数据库中salt字段的长度设置过小(比如VARCHAR(100)),存入时会被自动截断。登录时取出的是被截断的不完整salt,用它哈希密码自然和注册时的结果不一致。
- 修复:检查并修改数据库
salt字段的长度,设置为至少VARCHAR(255),确保能完整存储生成的salt字符串。
2. 查询结果处理逻辑错误
cursor.fetchone()返回的是包含字段值的元组(比如查询salt时返回('生成的salt字符串',)),如果你的convertselect函数没有正确提取元组中的实际salt值,会导致传入hash_algo的不是正确的字符串,而是元组或其他错误格式数据,哈希结果必然不匹配。
- 修复:可以直接跳过
convertselect,手动提取元组元素:
或者确认hashkey = cursor.fetchone()[0] # 取元组第一个元素,即实际salt值 hashedpass = cursor.fetchone()[0]convertselect函数的逻辑,确保它能将元组正确转换为对应字符串。
3. 登录阶段的冗余错误逻辑
登录代码最后存在完全错误的查询:
cursor.execute(f"""SELECT username FROM users WHERE username = '{username}' AND password = '{password}';""")
这里的password是用户输入的明文,而数据库存储的是哈希后的密码,这个查询永远不会返回结果,建议直接删除该冗余逻辑。
4. 致命SQL注入漏洞
你使用f-string拼接SQL语句的写法存在严重SQL注入风险,攻击者可通过构造特殊用户名直接操作数据库。
- 修复:和注册代码保持一致,使用参数化查询:
cursor.execute("""SELECT salt FROM users WHERE username = ?;""", (username,)) cursor.execute("""SELECT password FROM users WHERE username = ?;""", (username,))
额外优化建议
- SELECT操作无需调用
connect.commit(),可删除这些冗余语句。 - 合并两次查询为一次,减少数据库交互:
cursor.execute("""SELECT password, salt FROM users WHERE username = ?;""", (username,)) result = cursor.fetchone() if result: hashedpass, hashkey = result # 后续哈希对比逻辑 else: print("用户不存在")
内容的提问来源于stack exchange,提问作者abxty
相关产品推荐
相关产品推荐

