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

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

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

有帮助吗?

解决方案

更新:仅仅使用哈希函数不足以存储密码。你应该阅读 吉尔斯在此线程上的回答 以获得更详细的解释。

对于密码,请使用 Bcrypt 或 Argon2i 等密钥强化哈希算法。例如,在 PHP 中,使用 密码哈希函数, ,默认使用 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 位哈希值。 您可能需要 CHAR(56)、CHAR(60)、CHAR(76)、BINARY(56) 或 BINARY(60)

截至 2015 年,NIST 建议使用 SHA-256 或更高版本 适用于任何需要互操作性的哈希函数应用。但 NIST 不建议使用这些简单的哈希函数来安全地存储密码。

较小的哈希算法有其用途(例如应用程序内部,而不是用于交换),但它们是 已知可破解.

其他提示

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

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

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

始终使用密码哈希算法: 氩气2, 加密, 密码 或者 PBKDF2.

氩气2 赢得2015年密码哈希竞赛。 加密, 密码PBKDF2 是较旧的算法,现在被认为不太受欢迎,但从根本上来说仍然是合理的,因此如果您的平台尚不支持 Argon2,那么现在可以使用其他算法。

切勿将密码直接存储在数据库中。也不加密它:否则,如果您的网站遭到破坏,攻击者将获得解密密钥,从而获得所有密码。密码必须是 散列的.

A 密码哈希 与哈希表哈希或加密哈希具有不同的属性。切勿在密码上使用普通加密哈希,例如 MD5、SHA-256 或 SHA-512。密码哈希算法使用 , ,这是唯一的(不用于任何其他用户或任何其他人的数据库中)。加盐是必要的,这样攻击者就不能预先计算常用密码的哈希值:有了盐,他们就必须重新启动每个帐户的计算。密码哈希算法是 本质上很慢 ——尽可能慢。缓慢对攻击者的伤害比对你的伤害更大,因为攻击者必须尝试许多不同的密码。有关更多信息,请参阅 如何安全地散列密码.

密码哈希对四部分信息进行编码:

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

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

$算法$参数$$输出

在哪里 算法 是一个数字或一个短字母数字字符串,编码算法的选择, 参数 是一个可打印的字符串,并且 输出 以 Base64 编码而不终止 =.

16 个字节足以用于 salt 和输出。(参见例如 对 Argon2 的建议.) 采用 Base64 编码,每个字符 21 个。其他两部分取决于算法和参数,但通常为 20-40 个字符。这总共是 约 82 个 ASCII 字符 (CHAR(82), ,并且不需要 Unicode),如果您认为以后很难扩大该字段,则应该添加安全裕度。

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

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

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top