数据库中的密码安全 - 今天仍然是最佳实践吗?

信息安全 php mysql 哈希
2021-08-12 15:22:46

可能重复:
我应该使用哪种密码散列方法?

在堆栈溢出和其他站点上的数据库中有大量关于密码安全性的精彩帖子,由于我对此完全陌生,因此在过去的几天里我花了很多时间试图了解更多关于它的信息。但是,有很多不同的建议和最佳实践,我仍然很困惑......

此外,从 2007 年到 2010 年还有很多较旧的帖子等我看到事情变化的速度有多快,我不确定这是否仍然像他们建议的那样普遍使用。所以,我想总结一下我在帖子中发现的内容,然后询问我发现的这种方法是否是一个好习惯......

所以,这不是一个指南,而是一个总结,我知道这是非常基础的,如果有错误,请纠正我!

  1. 顺便提一下:您永远不应该存储纯文本密码:)
  2. 您“单向”散列密码,因此没有人可以看到纯文本。当用户输入密码时,您以相同的方式对其进行哈希处理,并将其与数据库中的哈希密码进行比较。
  3. 除了散列密码之外,您还应该对其进行加盐。您将盐添加到纯密码字符串并散列新字符串。如果普通密码很弱,添加盐会使其更长更强。
  4. 盐还应该是随机的(我读过术语“盐”意味着它无论如何都是随机的,否则它被称为“密钥”?)。这是为了防止彩虹表攻击,因为攻击者需要为每个盐创建一个表,这在时间等方面要昂贵得多。此外,如果两个用户具有相同的密码,如果您使用随机盐,您将无法识别它。
  5. 盐不是秘密!它存储在散列密码旁边的数据库中。但是,使用时间戳、用户的电子邮件地址或与用户相关的任何其他内容作为随机盐可能不是最好的主意。作为一个原因,例如提到用户倾向于在多个站点/服务上使用相同的密码。那么,盐应该是一个随机字符串,我读过最好的应该是 64 位的?
  6. 下一步是向散列过程添加迭代(1000 或更多循环),因此将盐添加到密码中,然后一遍又一遍地对其进行散列,这意味着用户在登录时只需等待几分之一秒中,但总结一下,如果您的数据库中有大约 10.000 个条目。
  7. 如果您添加一个站点密钥,这可能会带来一点好处,例如除了盐之外存储为全局变量。但是,您应该始终假设攻击者也可以访问您的文件系统。
  8. 哈希算法:我发现使用 MD5、SHA1 和其他弱方法肯定不再安全......

那么,对于是否使用 SHA256、SHA512 有不同的看法?你应该使用 hash_hmac 吗?有人说是的:(http://rdist.root.org/2009/10/29/stop-using-unsafe-keyed-hashes-use-hmac/)有人说使用库是唯一安全的方式......然后在一篇文章中我读过一次或两次不要将库用作 bcrypt 或泡泡鱼?

是否真的有必要使用库或者例如这样的方法就足够了:

function hash_password($password, $nonce) {

  for ($i = 0; $i < 5000; $i++) {
    $hashed_pass = hash_hmac('sha512', $hashed_pass . $nonce . $password, $site_key);
    }
  return $hashed_pass;
}

很多人说不要发明自己的算法,所以我有点害怕使用任何自己发明的东西。

我可以想象这很难预测,但是今天使用的方法能被认为足够安全多久?

更新:所以,感谢您的所有反馈。正如我看到的和你们中的许多人所说,缺少一个要点:密码安全,这意味着强密码是基本的。我想我收到了消息,再次感谢您!:)

更新 2:为了完成,我在http://www.lateralcode.com/creating-a-random-string-with-php/上找到了以下代码,用于生成随机盐:

function rand_string( $length ) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!§$%&/().-:;_#+*[]{}="; 

    $size = strlen( $chars );
    for( $i = 0; $i < $length; $i++ ) {
        $str .= $chars[ rand( 0, $size - 1 ) ];
    }

    return $str;
}

$random_salt= rand_string(20);
4个回答

你忘了一件小事:

密码强度。

仅仅 2 个词就足以让你的精彩话题变得更重要了。

Stackoverflow 上确实有数百个主题告诉您使用这个或那个散列算法和随机盐。
只有极少数人解释说,使用弱密码保护您的所有八项列表保护,所有具有 2048 字节长盐的额外安全 hmac-chmak-bumblemak 散列将在几秒钟内被破坏。

至于记不住$#%H4df84a$%#R密码的可怜用户——只要让他们使用的不是密码而是密码短语

Is it a good day today, Winkie? 使用不同的大小写字母以及推荐复杂度的密码,但更容易记住。

当然,这个短语不应该像“Joe”或“123”这样的常见密码那样普遍。
“早上好”,“天哪!他们杀了肯尼!” 应避免使用短语。
但是通过添加一些个性就可以了:
Oh My God! They moved Cthulhu!看起来足够了

另一件要提到的是服务器和浏览器之间的安全通信
没有它,一个简单的密码可以很容易地在通信中涉及的任何路由器上“嗅出”。

SSH 或Digest 授权的一些实现同样重要。

考虑到当前的计算能力,具有良好散列的通用散列函数(MD5、SHA1、SHA256)对于大多数小型网站来说可能足够安全。然而,摩尔定律将确保即使是好的密码在不久的将来也会受到暴力攻击。问题是哈希函数的计算速度可能太快了。最好的解决方案是使用具有大量迭代的 bcrypt 或 PBKDF2。http://security.stackexchange.com讨论了Bcrypt 与 PBKDF2

有些人可能认为这对大多数网站来说是多余的,但请记住,密码一直在重复使用,而且密码存储通常是在出现问题之前您不会更改的。

建议:

  1. 使用 bcrypt 或 PBKDF2。不要使用 SHA3 候选。它们可能包含尚未发现的安全漏洞。
  2. 使用随机盐来帮助防止彩虹表攻击。
  3. 强制用户选择密码。

更多信息

基本信息:

很好的问题,但我只能说这完全取决于使用情况。如果你只将它用于一个小网站,那么很有可能只有“脚本小子”会访问你,在这种情况下,一个简单的带盐的 SHA1 今天也完全足够了。在这种情况下,5-8-10 年甚至更长的时间是完全好的,脚本小子如果看到他们不能轻易闯入,他们就不会真正闯入它。如果您的网站由于某种原因受到攻击——金钱网站等,那么您应该使用最新的可用功能。在这种情况下,我什至会“冒险”使用非官方但已经移植的功能。现在有一个 SHA3 竞赛,对于有高额收入的网站,我会使用其中的 5 个竞争对手之一。

我说的要点很重要:

1.使用随机盐,甚至可能 20 个字符。破解密码变得更加困难,即使它们是可破解的,也需要花费太多时间才值得。
2.使用 SHA-1、SHA-2 或 WHIRLPOOL。用好盐,MD5 也可以,但我仍然建议这些。
3.如果用户的密码很简单,您可以使用任何出色的密码学。您必须确保他们使用包含大写、小写字母、数字和符号的非字典长密码,否则很容易被暴力破解。您可能会认为他们可能会被迫每年左右更改密码。

到代码:

循环多次可能很有用,但我认为不需要 5000。正常安全性的 3 是好的,或者 100,也许 1000 可以工作,但我认为 5000 太多了。SHA-256 很好,但您可以使用专门为此开发的算法,请参阅评论。

hash_hmac()函数将是一个不错的选择,它甚至可以克服较弱的哈希算法的问题。唯一的问题是,它太快了这意味着有了足够的 cpu-power(云),创建不同的彩虹表成为可能,这就是迭代的原因。如果您需要这种高安全性,那么您可以测量迭代所需的时间,然后计算给定时间所需的迭代次数。

编辑:

迭代可以解决这个问题,它应该以某种方式完成,即可以在以后增加迭代次数,而不会使现有哈希无效。这是适应新的未来硬件所必需的,但需要将散列参数与散列一起存储。

bcrypt 哈希算法就是为了满足这个需求而设计的,我写了一个如何在PHP 5.3 中使用bcrypt的小例子,我试着评论它,这样人们就可以理解发生了什么。