用于散列密码字段的数据类型和长度是多少?

时间:2008-10-29 15:44:47

标签: mysql hash types passwords cryptography

我不确定密码哈希是如何工作的(将在以后实现),但现在需要创建数据库模式。

我正在考虑将密码限制为4-20个字符,但据我所知,在加密哈希字符串之后会有不同的长度。

那么,如何将这些密码存储在数据库中?

10 个答案:

答案 0 :(得分:436)

更新:仅使用哈希函数不足以存储密码。您应该阅读the answer from Gilles on this thread以获得更详细的解释。

对于密码,请使用密钥加强哈希算法,如Bcrypt或Argon2i。例如,在PHP中,使用password_hash() function,默认情况下使用Bcrypt。

$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

结果是一个60个字符的字符串,类似于以下字符串(但数字会有所不同,因为它会产生一个独特的盐)。

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

使用SQL数据类型CHAR(60)存储Bcrypt哈希的此编码。请注意,此函数不会编码为十六进制数字的字符串,因此我们不能轻易地将其解析为以二进制形式存储。

其他哈希函数仍然有用,但不能用于存储密码,因此我将保留下面的原始答案,写于2008年。


这取决于您使用的散列算法。无论输入如何,散列总是产生相同长度的结果。通常将文本中的二进制哈希结果表示为一系列十六进制数字。或者您可以使用UNHEX()函数将十六进制数字字符串减半。

  • MD5生成128位哈希值。您可以使用CHAR(32)或BINARY(16)
  • SHA-1生成160位哈希值。您可以使用CHAR(40)或BINARY(20)
  • SHA-224生成224位哈希值。您可以使用CHAR(56)或BINARY(28)
  • SHA-256生成256位哈希值。您可以使用CHAR(64)或BINARY(32)
  • SHA-384生成384位哈希值。您可以使用CHAR(96)或BINARY(48)
  • SHA-512生成512位哈希值。您可以使用CHAR(128)或BINARY(64)
  • BCrypt生成依赖于实现的448位哈希值。 You might need CHAR(56), CHAR(60), CHAR(76), BINARY(56) or BINARY(60)

截至2015年,NIST recommends using SHA-256 or higher用于需要互操作性的哈希函数的任何应用程序。但NIST不建议使用这些简单的哈希函数来安全地存储密码。

较小的散列算法有其用途(如应用程序的内部,而非交换),但它们是known to be crackable

答案 1 :(得分:13)

您实际上可以使用CHAR(哈希长度)来定义MySQL的数据类型,因为每个哈希算法总是会计算出相同数量的字符。例如,SHA1始终返回40个字符的十六进制数字。

答案 2 :(得分:8)

您可能会发现有关盐腌worthwhile的维基百科文章。我们的想法是添加一组数据来随机化您的哈希值;如果有人未经授权访问密码哈希值,这将保护您的密码免受字典攻击。

答案 3 :(得分:7)

作为固定长度的字符串(VARCHAR(n)或MySQL调用它)。 散列总是固定长度,例如12个字符(取决于您使用的散列算法)。因此,20个字符的密码将减少为12个字符的哈希值,而4个字符的密码也会产生12个字符的哈希值。

答案 4 :(得分:4)

始终使用密码哈希算法:Argon2scryptbcryptPBKDF2

Argon2赢得了2015年密码哈希竞赛。 ScryptbcryptPBKDF2是较旧的算法,现在被认为较不受欢迎,但从根本上讲还是不错的,因此,如果您的平台尚不支持Argon2,则可以将另一种算法用于现在。

切勿将密码直接存储在数据库中。也不要对其进行加密:否则,如果您的站点遭到破坏,攻击者将获得解密密钥,因此可以获得所有密码。密码必须散列

密码哈希具有与哈希表哈希或密码哈希不同的属性。切勿在密码上使用普通的密码哈希,例如MD5,SHA-256或SHA-512。密码哈希算法使用唯一的 salt (不适用于任何其他用户或其他任何人的数据库)。盐是必不可少的,这样攻击者就不能仅预先计算常用密码的哈希值:使用盐,他们必须为每个帐户重新开始计算。密码哈希算法本质上很慢-尽你所能地慢。慢速攻击对您的伤害要比对您的伤害大得多,因为攻击者必须尝试许多不同的密码。有关更多信息,请参见How to securely hash passwords

密码哈希编码四段信息:

  • 使用哪种算法的指示符。这对于agility是必需的:加密建议会随时间而变化。您需要能够过渡到新算法。
  • 难度或硬度指示器。该值越高,则需要更多的计算来计算散列。在密码更改功能中,该值应该是常数或全局配置值,但是随着计算机变得越来越快,它应该随着时间的推移而增加,因此您需要记住每个帐户的值。有些算法只有一个数字值,其他算法那里有更多参数(例如分别调整CPU使用率和RAM使用率)。
  • 盐。由于盐必须是全局唯一的,因此必须为每个帐户存储。每次更改密码后都会随机生成盐。
  • 适当的哈希,即哈希算法中数学计算的输出。

许多库包含一对函数,可方便地将此信息打包为单个字符串:一个带有算法指示符,硬度指示符和密码,生成随机盐并返回完整的哈希字符串;另一个将密码和完整的哈希字符串作为输入,并返回一个布尔值,指示密码是否正确。没有通用标准,但是常见的编码是

$algorithm$parameters$salt$output

其中algorithm是一个数字或一个简短的字母数字字符串,用于编码算法选择,parameters是一个可打印的字符串,saltoutput在Base64中编码而没有终止=

16个字节足以容纳盐和输出。 (例如,参见recommendations for Argon2。)以Base64编码,每个21个字符。其他两个部分取决于算法和参数,但是典型的是20–40个字符。这总计大约82个ASCII字符CHAR(82),并且不需要Unicode),如果您认为以后很难扩展该字段,则应在其中添加安全边距

如果您以二进制格式对哈希进行编码,则对于算法,您可以将其降低到1个字节,对硬度可以将其降低到1-4个字节(如果您对某些参数进行硬编码),而对每个哈希则可以降低到16个字节盐和输出,总共37个字节。说 40个字节BINARY(40))至少要有几个备用字节。请注意,这些是8位字节,不是可打印字符,尤其是该字段可以包含空字节。

请注意,哈希的长度与密码的长度完全无关。

答案 5 :(得分:3)

这实际上取决于您正在使用的散列算法。如果我没记错的话,密码的长度与哈希的长度关系不大。查看您正在使用的散列算法的规范,运行一些测试,并在其上方截断。

答案 6 :(得分:3)

哈希是一系列位(128位,160位,256位等,具体取决于算法)。如果MySQL允许,您的列应该是二进制类型,而不是文本/字符类型(SQL Server数据类型为binary(n)varbinary(n))。你也应该给哈希加盐。盐可以是文本或二进制,您需要一个相应的列。

答案 7 :(得分:3)

为了向前兼容,您应该使用TEXT(存储无限数量的字符)。哈希算法(需要)随着时间的推移变得越来越强大,因此这个数据库领域需要随着时间的推移支持更多的字符。此外,根据您的迁移策略,您可能需要在同一字段中存储新旧哈希,因此不建议将长度固定为一种类型的哈希值。

答案 8 :(得分:1)

我一直在测试以查找加密字符串的MAX字符串长度,并将其设置为VARCHAR类型的字符长度。根据您将拥有的记录数量,它可以真正帮助数据库大小。

答案 9 :(得分:0)

对于md5 vARCHAR(32)是合适的。对于那些使用AES更好的人来说,使用varbinary。