我不确定密码哈希的工作原理(稍后将实现),但是需要立即创建数据库架构。
我正在考虑将密码限制为4-20个字符,但是据我了解,加密哈希字符串后的长度将不同。
那么,如何将这些密码存储在数据库中呢?
我不确定密码哈希的工作原理(稍后将实现),但是需要立即创建数据库架构。
我正在考虑将密码限制为4-20个字符,但是据我了解,加密哈希字符串后的长度将不同。
那么,如何将这些密码存储在数据库中呢?
Answers:
更新:仅使用哈希函数不足以存储密码。您应该阅读Gilles在该主题上的答案,以获取更详细的解释。
对于密码,请使用增强密钥的哈希算法,例如Bcrypt或Argon2i。例如,在PHP中,使用password_hash()函数(默认情况下使用Bcrypt)。
$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);
结果是一个类似于以下内容的60个字符的字符串(但是数字会有所不同,因为它会生成唯一的盐)。
$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a
使用SQL数据类型CHAR(60)
存储Bcrypt哈希的此编码。请注意,此函数不会编码为十六进制数字的字符串,因此我们无法轻松地将其以十六进制形式存储为二进制。
其他散列函数仍具有用途,但不能用于存储密码,因此我将保留原始答案,该答案写于2008年。
这取决于您使用的哈希算法。不管输入如何,散列总是产生相同长度的结果。通常用一系列十六进制数字将二进制哈希结果表示为文本。或者,您可以使用该UNHEX()
功能将十六进制数字的字符串减少一半。
自2015年起,NIST 建议将SHA-256或更高版本用于需要互操作性的哈希函数的任何应用程序。但是NIST不建议使用这些简单的哈希函数来安全地存储密码。
实际上,您可以使用CHAR
(哈希值的长度)为MySQL定义数据类型,因为每种哈希算法始终会得出相同数量的字符。例如,SHA1
始终返回40个字符的十六进制数字。
Argon2赢得了2015年密码哈希竞赛。Scrypt,bcrypt和PBKDF2是较旧的算法,现在被认为不那么但从根本上讲还是不错的,因此,如果您的平台尚不支持Argon2,则可以现在使用另一种算法。
切勿将密码直接存储在数据库中。也不要对其进行加密:否则,如果您的站点遭到破坏,攻击者将获得解密密钥,因此可以获得所有密码。密码必须被散列。
甲密码哈希具有从哈希表散列或密码散列不同的特性。切勿在密码上使用普通的密码哈希,例如MD5,SHA-256或SHA-512。密码哈希算法使用salt,它是唯一的(不用于任何其他用户或其他任何人的数据库)。盐是必不可少的,这样攻击者就不能仅预先计算常用密码的哈希值:使用盐,他们必须为每个帐户重新开始计算。密码哈希算法本质上很慢 -尽可能地慢。慢速攻击对您的伤害要比对您的伤害大得多,因为攻击者必须尝试许多不同的密码。有关更多信息,请参见如何安全地对密码进行哈希处理。
密码哈希编码四个信息:
许多库都包含一对函数,可方便地将此信息打包为单个字符串:一个带有算法指示器,硬度指示器和密码,生成随机盐并返回完整的哈希字符串的函数;另一个将密码和完整的哈希字符串作为输入,并返回一个布尔值,指示密码是否正确。没有通用标准,但是通用编码是
$ 算法 $ 参数 $ 盐 $ 输出
其中algorithm
是一个数字或编码算法的选择一个短字母数字串,parameters
是可打印字符串,salt
并output
以Base64而不终止被编码=
。
16个字节足以容纳盐和输出。(例如,参见有关Argon2的建议。)以Base64编码,每个21个字符。其他两个部分取决于算法和参数,但是典型的是20–40个字符。总共大约有82个ASCII字符(CHAR(82)
并且不需要Unicode),如果您认为以后很难扩展该字段,则应在其中添加安全边距。
如果您以二进制格式对哈希进行编码,则算法的哈希值可以减少到1个字节,硬度值可以减少到1-4个字节(如果您对某些参数进行了硬编码),salt和output可以分别减少到16个字节,共37个字节。说40个字节(BINARY(40)
)至少有几个备用字节。请注意,这些是8位字节,不是可打印字符,特别是该字段可以包含空字节。
请注意,哈希的长度与密码的长度完全无关。
您可能会发现Wikipedia上有关盐腌的文章值得。这个想法是添加一组数据来随机化您的哈希值。如果有人未经授权访问密码哈希,这将保护您的密码免受字典攻击。
作为固定长度的字符串(VARCHAR(n)或MySQL调用它)。哈希始终具有固定长度,例如12个字符(取决于您使用的哈希算法)。因此,将20个字符的密码减少为12个字符的哈希,而4个字符的密码也将产生12个字符的哈希。
这实际上取决于您使用的哈希算法。如果我没记错的话,密码的长度与哈希的长度无关。在您使用的哈希算法上查找规格,运行一些测试,然后在其上方截断。
哈希是一个位序列(128位,160位,256位等,具体取决于算法)。如果MySQL允许(SQL Server数据类型为binary(n)
或varbinary(n)
),则您的列应为二进制类型,而不是文本/字符类型。您还应该给哈希加盐。盐可能是文本或二进制,并且您将需要相应的列。