为啥 werkzeugs `generate_password_hash` 的输出不是恒定的?

Posted

技术标签:

【中文标题】为啥 werkzeugs `generate_password_hash` 的输出不是恒定的?【英文标题】:Why is the output of werkzeugs `generate_password_hash` not constant?为什么 werkzeugs `generate_password_hash` 的输出不是恒定的? 【发布时间】:2014-06-19 09:27:26 【问题描述】:

当我多次运行werkzeug.security.generate_password_hash("Same password") (docs) 时,每次的输出都不一样。

我做错了什么?为什么不恒定?

【问题讨论】:

原来我在将它存储在我的数据库中时截断了它。结果,我无法正确比较它:-) 感谢您提出这个问题 - 我正在重新散列以进行比较,而不是使用 check_password_hash() 方法。要不是为了回答这个问题,否则不会知道这样做。为你们俩点赞。 【参考方案1】:

密码是加盐,是的。在散列之前将盐添加到密码中,以确保散列在 rainbow table attack 中不可用。

因为每次调用函数时salt都是随机生成的,所以得到的密码hash也不同。返回的哈希包含生成的盐,以便仍然可以正确验证密码。

演示:

>>> from werkzeug.security import generate_password_hash
>>> generate_password_hash('foobar')
'pbkdf2:sha1:1000$tYqN0VeL$2ee2568465fa30c1e6680196f8bb9eb0d2ca072d'
>>> generate_password_hash('foobar')
'pbkdf2:sha1:1000$XHj5nlLU$bb9a81bc54e7d6e11d9ab212cd143e768ea6225d'

这两个字符串不同;但包含足够的信息来验证密码,因为生成的盐包含在每个:

# pbkdf2:sha1:1000$tYqN0VeL$2ee2568465fa30c1e6680196f8bb9eb0d2ca072d
  ^^^^^^^^^^^^^^^^   salt   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      algo info    ^^^^^^^^        actual hash of the password
  (PBKDF2 applied SHA1 1000 times)

因为随机盐是tYqN0VeL for one 和XHj5nlLU,所以得到的哈希值也不同。

foobar 密码仍然可以根据任一哈希进行验证:

>>> from werkzeug.security import check_password_hash
>>> check_password_hash('pbkdf2:sha1:1000$tYqN0VeL$2ee2568465fa30c1e6680196f8bb9eb0d2ca072d', 'foobar')
True
>>> check_password_hash('pbkdf2:sha1:1000$XHj5nlLU$bb9a81bc54e7d6e11d9ab212cd143e768ea6225d', 'foobar')
True

另见

Can you help me understand what a cryptographic “salt” is? (Cryptography.SE) Why is using salt more secure? (Security.SE)

【讨论】:

以上是关于为啥 werkzeugs `generate_password_hash` 的输出不是恒定的?的主要内容,如果未能解决你的问题,请参考以下文章

Flask -- 01. werkzeug请求与响应以及源码的解析

Werkzeug之LocalStack源码解析

Werkzeug之Local源码解析

Python Werkzeug 򕠍

werkzeug模版学习-官方例子Shortly分析

动手写一个简单的Web框架(Werkzeug路由问题)