PHP存储密码与河豚&盐与盐胡椒

时间:2013-02-21 13:52:18

标签: php hash salt blowfish crypt

我希望使用PHP将安全用户密码存储在MySQL数据库中。

如何让它变得更好?

我的班级:

private static $algo = '$2a';
private static $cost = '$10';
private static $pepper = 'eMI8MHpEByw/M4c9o7sN3d';

public static function generateSalt($length) {
    $randomBinaryString = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
    $randomEncodedString = str_replace('+', '.', base64_encode($randomBinaryString));
    return substr($randomEncodedString, 0, $length);
}

public static function generateHash($password) {
    if (!defined('CRYPT_BLOWFISH'))
        die('The CRYPT_BLOWFISH algorithm is required (PHP 5.3).');
    $password = hash_hmac('sha256', $password, self::$pepper, false);
    return crypt($password, self::$algo . self::$cost . '$' . self::generateSalt(22));
}

public static function checkPassword($hash, $password) {
    $salt = substr($hash, 0, 29);
    $password = hash_hmac('sha256', $password, self::$pepper, false);
    $new_hash = crypt($password, $salt);
    return ($hash == $new_hash);
}

1 个答案:

答案 0 :(得分:3)

使用this回答的建议(对于PHP> = 5.5)或以下类。感谢martinstoeckli指出password_hash函数。我阅读了代码,password_hash中唯一可以看到的不同之处是错误检查和操作系统DEV_URANDOM用法生成更随机的盐。

class PassHash {
    public static function rand_str($length) {
        $chars = "0123456789./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
        //only allowed chars in the blowfish salt.
        $size = strlen($chars);
        $str = "";
        for ($i = 0; $i < $length; $i++)
            $str .= $chars[rand(0, $size - 1)]; // hello zend and C.
        return $str;
    }
    public static function hash($input) {
        return crypt($input, "$2y$13$" . self::rand_str(22));
        // 2y is an exploit fix, and an improvement over 2a. Only available in 5.4.0+
    }
    public static function hash_weak($input) {
        return crypt($input, "$2a$13$" . self::rand_str(22)); }
        // legacy support, Add exception handling and fall back to <= 5.3.0
    public static function compare($input, $hash) {
        return (crypt($input, $hash) === $hash);
    }
}

这是我一直用的东西。建议也是PHPass。它经过了试验和测试。

<小时/> 这个脚本中唯一的缺点是我从rand()生成随机数,而不是来自操作系统的源,但这很容易改变。

此外,没有理由在bcrypt之上使用SHA256哈希。 SHA256很弱,可以用相对较少的努力打破 3

此外,散列密码是必不可少的做法,但为了真正的安全性,通过至少John the Ripperwordlist 1 运行所有输入删除最常用的密码并通知用户使用不同的密码。由于密码非常弱,所以Wordlists的使用效率远高于任何暴力。

<小时/> 最后, 不强制用户使用符号,大写和数字,强制他们使用长密码 2 。< p>

当涉及到强制密码时,长度就是一切(没有幽默意图)。除非编辑配置,否则几乎所有预设的破解者都将被设置为不超过12个字符。如果您在密码上看到一个“最大长度”的网站,请确保永远不要在那里重复使用密码,因为它们没有任何安全性 4

<小时/> 1.任意选择饼干;选择你发现最好的工作
2. http://xkcd.com/936/
3.相对而言(它的速度提高了几个数量级,并且在技术上通过默默无闻的安全性) 我甚至见过银行这样做。密码的最大长度使我切换银行。