【问题标题】:Password hash in PHP: Am I Doing This Right?PHP 中的密码哈希:我这样做对吗?
【发布时间】:2012-04-08 18:26:48
【问题描述】:

我正在尝试使用 PHP 创建一个登录系统,但我不太确定我的脚本是否真的很好,请查看以下内容。

所以,我创建了两个函数...其中一个用于创建哈希,另一个用于检查它。

查看函数:

function createSaltedPass($pass = false, $username = false) {
  if($pass && $username)
  {
    $salt = hash('sha256', uniqid( mt_rand(), true ) . md5(date('d m Y H i s') . " # ") . $username);

    $pass = hash('sha256', $salt . $pass . $salt);

    $pass = $salt . $pass;

    return $pass;
  }
}

上面的 sn-p 创建了一个巨大的哈希(具体是 128 个字符),我不知道它是否真的安全。

前半部分是盐,它让我可以在需要时检查它。

后半部分是真正的加盐密码。

查看密码示例:

939cf87873a402d48bcf66a57b64ca38d6f1db9155381ffe1aae9a469e93d1e7ec338071f2dd21a96ef5fc799a3f3921b0df3188458b17422db79271056a1fda

使用第一个功能后查看密码检查功能:

function checkSaltedPass($dbPass = false, $pass = false) {
  if($pass && $dbPass)
  {
    $salt = substr($dbPass, 0, 64);

    $pass = hash('sha256', $salt . $pass . $salt);

    $pass = $salt . $pass;

    return $pass;
  }
}

你怎么看?我不是安全方面的专家,如果有人能给我提示,我将不胜感激。

还有一件事:处理会话以保持用户登录的更好方法是什么?

(抱歉英语不好,这不是我的母语)。

【问题讨论】:

  • 你为什么要对盐进行两次散列?此外,checkSaltedPass 从不检查(散列的)密码是否匹配!
  • 好吧,第一部分创建盐的哈希,第二部分做同样的事情,但是将盐与密码一起使用,第三部分连接。盐和密码(这就是为什么我说密码的前 64 个字符 [hashed] 将是盐)。所以,我以后可以去看看。
  • 不需要hash salt+pass+salt;只是哈希盐+通过。第二次使用盐不会增加加密价值。也没有必要让哈希值真正随机化,只要每个密码不同即可。
  • 顺便说一句,+1 用于使用标准算法和技术,以及在实施它们之前进行仔细检查,而不是在系统受到威胁之后进行仔细检查。 :-)

标签: php mysql function hash passwords


【解决方案1】:

在这种情况下,密码与两个 sha1 散列字符串连接起来有点明显,攻击者更容易通过检查两个散列来暴力破解它,而盐在这里有点毫无意义,因为看看你的代码:什么是你做的只是……根本不检查!

在我看来,您可以稍后将静态安全盐与静态用户信息(例如注册日期、注册 IP 等)连接起来。

然后用法看起来像这样:

$pass = sha1($password . $staticSalt . $registerDate);

这样做的好处是,如果即使是攻击者也会发现与蛮力的冲突,那么在将找到的字符串放入 password 字段后,密码将评估为:

$bruteForcedPassword . $staticSalt . $registerDate

这与用户的哈希密码仍然不同。

在这个方法中,攻击者必须知道你的静态安全盐,你如何构建密码字符串和用户的注册日期(或其他组合到密码中的东西)。

另请阅读timing attacks

编辑: 或者只是使用这个library for password hashing

【讨论】:

  • 但是如果黑客窃取了你的数据库,我认为这有点困难(但谁知道),他将能够在使用暴力破解后找到形成密码所需的所有信息方法。
  • 查看硬编码的静态安全盐。即使他得到你的数据库,他也有信息,但他怎么知道你是如何创建哈希的?您使用了哪些信息?他需要一个代码,如果得到代码 - 没有什么能拯救你:P
【解决方案2】:

我觉得这个功能比较多余 uniqid 已经基于当前时间。

function createSaltedPass($pass) {
    $salt = hash('sha256', uniqid( mt_rand(), true ));
    $pass = hash('sha256', $salt . $pass);
    return $salt . $pass;
}

我觉得够用了

但是,所有这些散列的东西都无关紧要。
真正重要的是密码强度。
对于弱密码散列是没有用的。

【讨论】:

  • 是的,我也想过。我会改的。
【解决方案3】:

您应该使用crypt() 而不是hash() 函数。它更适合散列密码。它还可以让您将盐和哈希存储在一起。

至于保持用户登录,当您关闭标签/浏览器时会话结束。如果您想让您的用户登录更长时间,您将不得不使用 cookie。

我建议使用“受保护”cookie:

数据 |时间戳 |验证哈希

验证哈希是从data + timestamp + some predefined string 创建的。这使您可以确保用户没有弄乱data 部分。另外,我会警告不要为此使用IP。虽然这会增加额外的保护,但也会让移动设备(包括笔记本电脑)的使用有些烦人。

【讨论】:

  • 我只是在这里检查地穴...但是,在那种情况下我将无法使用相同的功能...至少我是这么认为的(我没有真正测试过可以肯定的是)
猜你喜欢
  • 2019-05-18
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 2012-08-13
  • 2023-03-19
相关资源
最近更新 更多