【问题标题】:Salting and hashing passwords in MySQLMySQL中的加盐和散列密码
【发布时间】:2014-06-10 07:24:49
【问题描述】:

我正在寻找一种使用盐存储和验证 mysql 密码的方法。我无权使用 PHP 或任何其他加密软件。我知道 PASSWORD() 函数,但不允许使用盐。

还有其他选择吗?

【问题讨论】:

  • MySQL 用户密码不使用盐。您确定这些是 MySQL 用户密码吗?你确定不想要SHA1()
  • 也许我是模棱两可的。我不是在谈论 mysql 用户,我是在谈论将密码存储在自己的表中。

标签: mysql passwords cryptography


【解决方案1】:

我假设既然您在谈论盐,那么您的真正意思是散列,这是一种单向密码学形式,而不是加密。哈希保证给定的输入值总是产生相同的输出值。使用安全散列算法,除了尝试散列函数中的每个明文值之外,没有更好的方法来导出原始明文。

虽然 SHA1 可能足以保护许多系统的密码,但肯定有更好的散列算法。然而,SHA1 在 MySQL 中可用。

虽然SHA1() MySQL 函数不接受单独的加盐参数,但您仍然可以加盐密码。事实上,我知道的大多数哈希函数都没有单独的盐参数。

要对明文值加盐,只需将随机字符串连接到明文值的开头即可。不幸的是,MySQL 没有直接的方法来生成随机字符串,但这会让你很接近。

要生成一个 6 个字符(仅限十六进制值)的随机字符串:

SELECT SUBSTRING(SHA1(RAND()), 1, 6) AS salt

当然,重要的是您必须始终保存盐分。你会再次需要它。

保存盐后,只需像这样对密码进行哈希处理:

SELECT SHA1(CONCAT(salt, 'password')) AS hash_value

通常通过在哈希值前加上盐来将盐和哈希密码存储在同一列中。

要验证输入的密码,只需重复该过程。用存储的盐作为明文密码的前缀,对连接的字符串进行哈希处理,然后将生成的哈希值与存储的密码哈希值进行比较。

每条记录应该有不同的随机盐。

【讨论】:

  • SHA1() 会比 PASSWORD() 更好吗?下面的工作吗? SELECT PASSWORD(CONCAT(salt, 'password')) AS hash_value
  • @trex005,是的,这行得通。看来 PASSWORD() 函数与 SHA1(UNHEX(SHA1(password))) 相同,带有一个额外的星号前缀,因此 MySQL 知道它的“新”格式。我不会使用PASSWORD(),除非他们改变了实现。为 MySQL 密码保留 PASSWORD()
【解决方案2】:

很遗憾,仅使用 SQL 命令无法安全地存储密码。

由于您应该在哈希方案中添加随机盐,因此如果用户尝试登录,您将无法验证密码。您必须读取用户表中每一行的盐值并计算哈希值以进行比较。

一个安全的散列函数可以调整为需要一定的时间(例如 10 毫秒),例如 BCrypt 有一个成本因素。如果您必须检查每一行并且每次计算都需要一些时间,那么如果您的用户表增长,您将遇到问题。

这就是为什么密码不应该由数据库本身散列的原因。首先,您必须通过给定的用户名找到哈希及其盐,然后您可以验证这一行的密码。

【讨论】:

    【解决方案3】:

    这里有两个很棒的链接:

    http://www.aspheute.com/english/20040105.asp

    http://alias.io/2010/01/store-passwords-safely-with-php-and-mysql/

    首先,您不想“加密”您的密码。加密意味着它们可以被解密,这……不是一件好事。您希望对它们进行哈希处理,使它们成为单向票证(例如 SHA512())。

    注意:MD5 不应该用于安全密码散列。很容易被破解。

    这是我看到的简化/解释的盐:Salt 将随机值添加到密码哈希中。 Salt对于每个密码都是唯一的。 (每个密码的盐需要与密码一起存储)。每个密码都有唯一的盐,字典攻击(密码破解技术)基本上没有机会。

    因此,只需在您的密码中添加盐,例如:

    $salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');
    

    并将其与密码一起存储,或作为 cookie 存储,或两者兼而有之。

    希望对您有所帮助。

    【讨论】:

    • 如问题所述,我无权访问 php
    • Salt 对字典攻击没有帮助,这只是暴力攻击的一种形式。盐确实有助于彩虹攻击。简单地说,盐是为了使具有相同密码的帐户仍然具有不同的哈希值。
    • 我不敢苟同。据我了解,字典攻击使用/操纵 WORDS 到密码中,例如,“secretpass”到“secretpassword”到“s3cretp4ssw0rd”等变体。然而,Salt 会将其设为“secretpassword4:003f93j3fd3”(散列)。