使用flask-bcrypt生成和验证密码哈希

5 投票
1 回答
4949 浏览
提问于 2025-04-18 02:27

最近我学会了如何在数据库中存储密码,方法是给明文密码加一个“盐”,然后对它进行哈希处理,最后存储这个哈希值。

我正在做一个非常简单的Flask应用来试验这些东西,但在密码哈希和检查的过程中遇到了一些问题。看起来我对同样的输入得到了两个不同的哈希值,我搞不清楚为什么会这样。

我在解释器里做了一个小实验来测试一下。

>>> from os import urandom
>>> salt = urandom(32).encode('base-64')
>>> salt
'+3DejJpQZO9d8campsxOB6fam6lBE0mJ/+UvFf3oG8c=\n'
>>> plaintext_pw = 'archer'
>>> plaintext_pw
'archer'
>>> salted_pw = plaintext_pw + salt
>>> salted_pw
'archer+3DejJpQZO9d8campsxOB6fam6lBE0mJ/+UvFf3oG8c=\n'
>>> from flaskext.bcrypt import Bcrypt
>>> bc = Bcrypt(None)
>>> hashed_pw = bc.generate_password_hash(salted_pw)
>>> hashed_pw
'$2a$12$znMwqAw.GliVE8XFgMIiA.aEGU9iEZzZZWfxej5wSUFP0huyzdUfe'

到目前为止一切都很好,但当我转过来做这个时:

>>> bc.generate_password_hash(plaintext_pw + salt)
'$2a$12$qbywkEjuJgmBvXW6peHzAe.rWjoc.ybFKRNzuZhom2yJSXaMRcVTq'

我得到了一个完全不同的哈希值,尽管我使用的是相同的明文密码和盐。我以为这种情况不应该发生?而且每次调用bc.generate_password_hash()时,结果都不一样:

>>> bc.generate_password_hash(plaintext_pw + salt)
'$2a$12$FAh9r4oaD40mWPtkClAnIOisP37eAT5m.i.EGV1zRAsPNbxg3BlX2'
>>> bc.generate_password_hash(plaintext_pw + salt)
'$2a$12$gluk9RUiR6D0e2p1J.hNgeE3iTFxDUlCNvFJOsCZZk89ngO.Z6/B6'

据我所知,明文密码和盐在每次调用之间并没有变化。我似乎找不到错误,能不能有人给我解释一下这里到底发生了什么,以及我做错了什么?

1 个回答

11

好的,看起来我解决了我的问题。原来我没有正确使用bcrypt。以下是我学到的:

每次我调用generate_password_hash时,生成的哈希值都是不同的,因为bcrypt会自动为你生成一个盐值,并把它加到哈希密码里,所以不需要自己用urandom生成盐值或者单独存储它。

我在帖子里没有提到这一点,但这里值得一提 - 我原以为在登录时需要调用generate_password_hash()并提供登录表单中的密码,以创建第二个哈希供check_password_hash()进行比较,但其实并不需要。check_password_hash()可以直接用存储的哈希和表单中的密码来调用,它会自动处理盐值和哈希的过程,并将表单密码与存储的哈希进行比较。

现在一切都正常工作了。希望这能帮助到其他人!

撰写回答