我想在数据库中存储一个散列密码(使用 BCrypt)。什么是一个好的类型,哪个是正确的长度?使用 BCrypt 散列的密码是否总是相同的长度?
编辑
示例哈希:
$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu
在对一些密码进行哈希处理后,BCrypt 似乎总是生成 60 个字符的哈希值。
编辑 2
很抱歉没有提到实施。我正在使用jBCrypt。
bcrypt 的模块化 crypt 格式包括
$2$
,$2a$
或$2y$
识别散列算法和格式$
.
字母的字母表, /
, 0
–<code>9, A
–<code>Z, –<code>z ),包括:
a
因此总长度分别为 59 或 60 个字节。
当您使用 2a 格式时,您将需要 60 个字节。因此对于 MySQL,我建议使用CHAR(60) BINARY
orBINARY(60)
(有关差异的信息,请参阅_bin和二进制排序规则)。
CHAR
不是二进制安全的,相等性不仅仅取决于字节值,还取决于实际的排序规则;在最坏的情况下A
被视为等于a
。有关详细信息,请参阅The_bin
和binary
Collations。
Bcrypt 哈希可以存储在BINARY(40)
列中。
BINARY(60)
,正如其他答案所暗示的那样,是最简单和最自然的选择,但如果您想最大限度地提高存储效率,您可以通过无损解构散列来节省 20 个字节。我在 GitHub 上对此进行了更详尽的记录:https ://github.com/ademarre/binary-mcf
Bcrypt 哈希遵循称为模块化密码格式 (MCF) 的结构。二进制MCF (BMCF) 将这些文本哈希表示解码为更紧凑的二进制结构。在 Bcrypt 的情况下,生成的二进制哈希是 40 字节。
Gumbo 很好地解释了 Bcrypt MCF 哈希的四个组成部分:
$<id>$<cost>$<salt><digest>
解码为 BMCF 如下所示:
$<id>$
可以用 3 位表示。<cost>$
, 04-31, 可以用 5 位表示。将这些放在一起 1 个字节。1 + 16 + 23
您可以在上面的链接中阅读更多内容,或者在 GitHub 上查看我的 PHP 实现。
如果您将 PHPpassword_hash()
与PASSWORD_DEFAULT
算法一起使用来生成 bcrypt 哈希(我假设有很大一部分人会阅读此问题),请务必记住,将来password_hash()
可能会使用不同的算法作为默认算法,因此这可能影响哈希的长度(但不一定更长)。
从手册页:
请注意,此常量旨在随着 PHP 中添加新的和更强大的算法而随时间而变化。因此,使用此标识符的结果长度可能会随时间而变化。因此, 建议将结果存储在可以扩展超过 60 个字符的数据库列中(255 个字符将是一个不错的选择)。
使用 bcrypt,即使你有 10 亿用户(即你目前正在与 facebook 竞争)来存储 255 字节的密码哈希,它也只会存储大约 255 GB 的数据——大约是一个小型 SSD 硬盘的大小。存储密码哈希极不可能成为应用程序的瓶颈。但是,如果由于某种原因存储空间确实是PASSWORD_BCRYPT
一个问题,您可以使用强制password_hash()
使用 bcrypt,即使这不是默认设置。请务必随时了解 bcrypt 中发现的任何漏洞,并在每次发布新的 PHP 版本时查看发行说明。如果默认算法发生更改,最好检查原因并做出是否使用新算法的明智决定。
我不认为您可以使用任何巧妙的技巧来存储它,例如使用 MD5 哈希。
我认为你最好的选择是将它存储为 aCHAR(60)
因为它总是 60 个字符长