MySQL 我应该使用什么列类型/长度来在数据库中存储 Bcrypt 哈希密码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5881169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 19:45:43  来源:igfitidea点击:

What column type/length should I use for storing a Bcrypt hashed password in a Database?

mysqlhashtypesstoragebcrypt

提问by helpermethod

I want to store a hashed password (using BCrypt) in a database. What would be a good type for this, and which would be the correct length? Are passwords hashed with BCrypt always of same length?

我想在数据库中存储散列密码(使用 BCrypt)。什么是好的类型,哪个是正确的长度?使用 BCrypt 散列的密码是否总是长度相同?

EDIT

编辑

Example hash:

示例哈希:

$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu

$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu

After hashing some passwords, it seems that BCrypt always generates 60 character hashes.

在对一些密码进行哈希处理后,BCrypt 似乎总是生成 60 个字符的哈希值。

EDIT 2

编辑 2

Sorry for not mentioning the implementation. I am using jBCrypt.

很抱歉没有提到实现。我正在使用jBCrypt

回答by Gumbo

The modular crypt format for bcrypt consists of

bcrypt 的模块化 crypt 格式包括

  • $2$, $2a$or $2y$identifying the hashing algorithm and format
  • a two digit value denoting the cost parameter, followed by $
  • a 53 characters long base-64-encoded value (they use the alphabet ., /, 09, AZ, azthat is different to the standard Base 64 Encodingalphabet) consisting of:
    • 22 characters of salt (effectively only 128 bits of the 132 decoded bits)
    • 31 characters of encrypted output (effectively only 184 bits of the 186 decoded bits)
  • $2$,$2a$$2y$确定散列算法和格式
  • 表示成本参数的两位数值,后跟 $
  • 一个 53 个字符长的 base-64 编码值(它们使用字母., /, 09, AZ, az这与标准的 Base 64 Encoding字母表不同)包括:
    • 盐的 22 个字符(实际上只有 132 个解码位中的 128 个位)
    • 加密输出的 31 个字符(实际上只有 186 个解码位中的 184 个位)

Thus the total length is 59 or 60 bytes respectively.

因此总长度分别为 59 或 60 字节。

As you use the 2a format, you'll need 60 bytes. And thus for MySQL I'll recommend to use the CHAR(60) BINARYor BINARY(60)(see The _binand binaryCollationsfor information about the difference).

当您使用 2a 格式时,您将需要 60 个字节。因此,对于 MySQL,我建议使用CHAR(60) BINARYorBINARY(60)(有关差异的信息,请参阅The _binbinaryCollat​​ions)。

CHARis not binary safe and equality does not depend solely on the byte value but on the actual collation; in the worst case Ais treated as equal to a. See The _binand binaryCollationsfor more information.

CHAR不是二进制安全的,相等性不仅取决于字节值,还取决于实际的排序规则;在最坏的情况下A被视为等于a。有关更多信息,请参阅The_binbinaryCollat​​ions

回答by Andre D

A Bcrypt hash can be stored in a BINARY(40)column.

Bcrypt 哈希可以存储在BINARY(40)列中。

BINARY(60), as the other answers suggest, is the easiest and most natural choice, but if you want to maximize storage efficiency, you can save 20 bytes by losslessly deconstructing the hash. I've documented this more thoroughly on GitHub: https://github.com/ademarre/binary-mcf

BINARY(60),正如其他答案所暗示的那样,是最简单和最自然的选择,但如果您想最大限度地提高存储效率,则可以通过无损解构散列来节省 20 个字节。我已经在 GitHub 上更彻底地记录了这一点:https: //github.com/ademarre/binary-mcf

Bcrypt hashes follow a structure referred to as modular crypt format (MCF). BinaryMCF (BMCF) decodes these textual hash representations to a more compact binary structure. In the case of Bcrypt, the resulting binary hash is 40 bytes.

Bcrypt 哈希遵循称为模块化加密格式 (MCF) 的结构。二进制MCF (BMCF) 将这些文本哈希表示解码为更紧凑的二进制结构。在 Bcrypt 的情况下,生成的二进制哈希是 40 个字节。

Gumbo did a nice job of explaining the four components of a Bcrypt MCF hash:

Gumbo 很好地解释了 Bcrypt MCF 哈希的四个组成部分:

$<id>$<cost>$<salt><digest>

Decoding to BMCF goes like this:

解码为 BMCF 是这样的:

  1. $<id>$can be represented in 3 bits.
  2. <cost>$, 04-31, can be represented in 5 bits. Put these together for 1 byte.
  3. The 22-character salt is a (non-standard) base-64 representation of 128 bits. Base-64 decoding yields 16 bytes.
  4. The 31-character hash digest can be base-64 decoded to 23 bytes.
  5. Put it all together for 40 bytes: 1 + 16 + 23
  1. $<id>$可以用3位表示。
  2. <cost>$, 04-31, 可以用5位表示。将这些放在一起为 1 个字节。
  3. 22 个字符的盐是 128 位的(非标准)base-64 表示。Base-64 解码产生 16 个字节。
  4. 31 个字符的哈希摘要可以通过 base-64 解码为 23 个字节。
  5. 将它们放在一起 40 个字节: 1 + 16 + 23

You can read more at the link above, or examine my PHP implementation, also on GitHub.

您可以在上面的链接中阅读更多内容,或者在 GitHub 上检查我的 PHP 实现

回答by Mike

If you are using PHP's password_hash()with the PASSWORD_DEFAULTalgorithm to generate the bcrypt hash (which I would assume is a large percentage of people reading this question) be sure to keep in mind that in the future password_hash()might use a different algorithm as the default and this could therefore affect the length of the hash (but it may not necessarily be longer).

如果您使用的是PHP的password_hash()使用PASSWORD_DEFAULT算法来生成bcrypt哈希(我会假设是人们阅读这个问题有很大比例)一定要记住,在未来password_hash()可能会使用不同的算法作为默认设置,因此,这可能影响散列的长度(但不一定更长)。

From the manual page:

从手册页:

Note that this constant is designed to change over time as new and stronger algorithms are added to PHP. For that reason, the length of the result from using this identifier can change over time. Therefore, it is recommended to store the result in a database column that can expand beyond 60 characters(255 characters would be a good choice).

请注意,此常量旨在随着新的和更强大的算法添加到 PHP 中而随时间变化。出于这个原因,使用此标识符的结果的长度可能会随着时间而改变。因此, 建议将结果存储在可以扩展到 60个字符以上的数据库列中(255 个字符将是一个不错的选择)。

Using bcrypt, even if you have 1 billion users (i.e. you're currently competing with facebook) to store 255 byte password hashes it would only ~255 GB of data - about the size of a smallish SSD hard drive. It is extremely unlikely that storing the password hash is going to be the bottleneck in your application. However in the off chance that storage space really isan issue for some reason, you can use PASSWORD_BCRYPTto force password_hash()to use bcrypt, even if that's not the default. Just be sure to stay informed about any vulnerabilities found in bcrypt and review the release notes every time a new PHP version is released. If the default algorithm is ever changed it would be good to review whyand make an informed decision whether to use the new algorithm or not.

使用 bcrypt,即使您有 10 亿用户(即您目前正在与 facebook 竞争)来存储 255 字节的密码哈希,它也只有 ~255 GB 的数据 - 大约是小型 SSD 硬盘的大小。存储密码哈希极不可能成为应用程序中的瓶颈。但是,如果由于某种原因存储空间确实一个问题,您可以使用PASSWORD_BCRYPT强制password_hash()使用 bcrypt,即使这不是默认设置。请务必随时了解 bcrypt 中发现的任何漏洞,并在每次发布新的 PHP 版本时查看发行说明。如果默认算法发生过更改,最好查看原因并做出是否使用新算法的明智决定。

回答by James C

I don't think that there are any neat tricks you can do storing this as you can do for example with an MD5 hash.

我不认为有任何巧妙的技巧可以存储它,例如使用 MD5 哈希可以做到的。

I think your best bet is to store it as a CHAR(60)as it is always 60 chars long

我认为最好的办法是将它存储为 aCHAR(60)因为它总是 60 个字符长