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

我是否正确实现了密码的哈希与加盐?

密码哈希加盐代码的问题与数据库存储方案

代码问题修正

你的代码存在核心缺陷:生成的随机盐没有和哈希值一起留存,后续验证密码时无法复用相同的盐,导致无法正确校验密码。以下是修正后的代码,同时添加了密码验证逻辑:

import hashlib
import os

password = input("Create Password: ")

def hash_new_password(password):
    # 生成16字节的随机盐
    salt = os.urandom(16)
    # 基于PBKDF2-HMAC生成密码哈希
    hash_result = hashlib.pbkdf2_hmac('blake2b', password.encode('utf-8'), salt=salt, iterations=100000)
    # 将盐和哈希值转为十六进制字符串,用$分隔后返回
    return f"{salt.hex()}${hash_result.hex()}"

def verify_password(stored_credential, input_password):
    # 拆分存储的盐和哈希值
    salt_hex, stored_hash = stored_credential.split('$')
    salt = bytes.fromhex(salt_hex)
    # 用相同参数生成输入密码的哈希
    input_hash = hashlib.pbkdf2_hmac('blake2b', input_password.encode('utf-8'), salt=salt, iterations=100000)
    # 用常量时间比较避免时序攻击
    return hashlib.compare_digest(input_hash.hex(), stored_hash)

# 生成带盐的哈希凭证
hashed_credential = hash_new_password(password)
print(hashed_credential)

# 验证示例(可注释掉)
# is_valid = verify_password(hashed_credential, input("Enter Password to Verify: "))
# print("Password Valid:", is_valid)

数据库存储方案

有两种常见的存储方式,按需选择:

方式一:单字段存储拼接字符串

  • 在数据库表中创建一个字段(比如hashed_password),字段类型设为VARCHAR(255)(长度足够容纳盐和哈希的十六进制字符串)。
  • 将hash_new_password返回的拼接字符串(格式为盐十六进制$哈希十六进制)直接存入该字段。
  • 验证时,从数据库取出该字段值,传入verify_password函数即可。

方式二:双字段分别存储

  • 在数据库表中创建两个字段:
    • salt:类型VARCHAR(64),存储盐的十六进制字符串;
    • password_hash:类型VARCHAR(256),存储哈希值的十六进制字符串。
  • 存储时,拆分hash_new_password返回的字符串,将盐和哈希值分别存入对应字段。
  • 验证时,取出两个字段的值,拼接成盐$哈希格式的字符串,再传入verify_password函数,或者直接修改验证函数接收盐和哈希两个参数。

注意事项

  • 绝对不要存储明文密码,只留存盐和哈希值。
  • 字段长度不要设置过短,避免截断盐或哈希值导致验证失败。
  • 验证时必须使用常量时间比较(如代码中的hashlib.compare_digest),防止时序攻击泄露信息。

内容的提问来源于stack exchange,提问作者NukaWinter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:48:26