【问题标题】:Storing passwords with sha1 and salt使用 sha1 和 salt 存储密码
【发布时间】:2012-10-18 09:22:22
【问题描述】:

我有一个用 php 完成的简单注册脚本,我只是好奇我这样做的方式是否足够安全以存储用户密码。我正在生成一个 32 位随机盐并将其附加到一个 sha1 散列密码。

//create new validator object
    $validator = new data_validation();
    //validate user input
    $firstName = $validator->validate_fname($firstName); //is the first name a string?
    $lastName = $validator->validate_lname($lastName); // is the last name a string?
    $username = $validator->validate_username($username); // is the username a string?
    $email = $validator->validate_email($email); //is the email in valid format?

    //make sure there isn't duplicate emails
    $valQuery = $link->query("SELECT email FROM users WHERE email = '" .$email. "'");

    if ($valQuery->num_rows == 1) {
        echo "An email is already registered with that address";
        return false;
    }

    // generate a random salt for converting passwords into sha1
    $salt = $link->real_escape_string(bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)));
    $saltedPW =  $password . $salt;
    $hashedPW = sha1($saltedPW);

    mysqli_connect($db_host, $db_user, $db_pass) OR DIE (mysqli_error());
    // select the db
    mysqli_select_db ($link, $db_name) OR DIE ("Unable to select db".mysqli_error($db_name));

     // our sql query
    $sql = "INSERT INTO users (first_name, last_name, username, email, password, salt) VALUES ('$firstName', '$lastName', '$username', '$email', '$hashedPW', '$salt');";

    //save the updated information to the database          
    $result = mysqli_query($link, $sql) or die("Error in Query: " . mysqli_error($link));

    if (!mysqli_error($link)) 
    {
        $row = mysqli_fetch_assoc($result);
        $_SESSION['user_id'] = $row['user_id'];
        $_SESSION['loggedin'] = TRUE;
        header("Location: ../home");
    }

另外,我正在使用程序和 oop php 的组合。其中大部分是在程序中完成的,但也有一些 oop 类,例如您在上面的脚本中看到的验证类。这会导致使用这两种样式的任何性能问题吗?

【问题讨论】:

  • 根本不是重复的。我没有看到任何与我的脚本或问题相似的内容?我想我只是想了解一下这个脚本是否足够安全以大规模存储用户密码?
  • @TyBailey 您的问题只是该问题的一个具体案例——如何在 PHP 中安全地散列密码。该问题的答案也适用于您的问题(不,您的方法不安全)。
  • 这就是你要说的。无需指责我发布重复的问题。我很欣赏您在下面的回答,但仅仅因为一些问题被问到类似并不意味着它们是重复的。您指向的问题充满了有用的信息,但它没有回答我的问题。然而,你做到了。所以谢谢你。

标签: php hash mysqli sha1 salt


【解决方案1】:

没有。停止你正在做的事情,阅读How to securely hash passwords,然后阅读Secure hash and salt for PHP passwords

最重要的是:

  • 尽可能使用 scrypt;如果不能,请使用 bcrypt。
  • 如果您不能使用 bcrypt 或 scrypt,请使用 PBKDF2。

请参阅this answer 了解 PBKDF2、bcrypt 和 scrypt 的比较。

也可以参考经常链接的文章How To Safely Store A Password

[MD5, SHA1, SHA256, SHA512, SHA-3, etc] 都是通用的散列函数,旨在尽可能短的时间内计算出海量数据的摘要。这意味着它们非常适合确保数据的完整性,而存储密码则完全是垃圾。

PHPass 可能是在 PHP 中进行 bcrypt 散列的最简单方法。如果需要,您也可以使用 crypt functionCRYPT_BLOWFISH do it the hard way,但请注意,有很多方法会出错,而且界面相当晦涩(就像您指定盐值的方式一样)。

【讨论】:

  • 感谢您的提示! -- 你能解释一下 bcrypt 和 scrypt 之间的区别以及为什么 scrypt 更安全吗?我阅读了您指示我访问的一些信息,但它们都没有提供两者的比较。
  • @TyBailey this question I asked a while ago 有一些很好的解释。简短的版本是有这三个主要的关键派生函数: PKBDF2 通过让您调整要运行的哈希函数的迭代次数来使用可变数量的处理器时间,但它很容易在硬件中实现(这很糟糕)。 bcrypt 还使处理器时间可控,但在硬件中实现相对昂贵。 scrypt 具有可变的 CPU 时间和内存要求,而且内存在硬件实现中真的很昂贵。
  • 另外,PBKDF2 是一个IETF standard,在某些情况下可能很重要(如果您需要使用它)。我认为 PBKDF2 和 bcrypt 都大约有 12 年的历史,而 scrypt 只是几年前。在安全性方面,旧的更好(主要是因为它是我们拥有的唯一证据,证明一个函数不是容易被破坏的)。找到 PBKDF2 和 bcrypt 的实现也容易得多,因为它们太老了。
【解决方案2】:

在程序和 OO 之间切换本身不会影响性能。加载和实例化类的开销可以忽略不计。但是,管理不断增长的非 OO 代码库可能是一项不可忽视的任务——尤其是在全局命名空间中处理所有事情。

在插入中添加一个额外的字段(盐)也不会影响任何事情。使用 salt 不会通过将 sha1 算法附加到密码末尾来增加开销。

我对你如何选择生成随机盐有点困惑,但它看起来也不是很系统密集。

【讨论】:

  • 那么盐到底有什么作用呢?它为每个密码生成一个随机盐,将其附加到密码,然后 sha1 的密码附加了生成的盐。你是说我不需要将它存储在数据库中?
  • 不,它可以生成和存储(你需要它来解密),但我发现你这样做的方式很有趣。
猜你喜欢
  • 1970-01-01
  • 2015-10-19
  • 2012-06-10
  • 1970-01-01
  • 2014-08-16
  • 2014-08-01
  • 2012-07-05
  • 1970-01-01
  • 2011-06-23
相关资源
最近更新 更多