在mysql数据库中存储密码的最佳方式是什么?

7

2
相关内容:如何安全地哈希密码? - Brendan Long
1
@JvdBerg - 在2012年,使用GPU进行1.9E9个组合的尝试大约需要0.25秒。无需将它们存储在硬盘上,只需尝试(暴力破解)直到找到匹配项即可。 - martinstoeckli
我的观点是关于MD5的所有恐怖故事都是缺乏背景的。一个密码+UTF-8盐,长度足够长的话,可以安全保存更多的年份。 - JvdBerg
1
@JvdBErg - 这是一个误解,盐不能计入密码长度,它不是一个秘密,并将与密码哈希一起存储。使用SQL注入攻击,您将获得此盐。 - martinstoeckli
1
@JvdBerg - 实际上这是关键!它保护您用户的密码,以防攻击者获得带有密码哈希的数据库访问权限。这些密码通常也用于其他网站。 - martinstoeckli
显示剩余14条评论
5个回答

9
我建议使用bcrypt,因为它可以防止暴力攻击。你可以在这里找到更多信息。
这里可以找到示例。

2
bcrypt是唯一一个专门设计成难以破解的方法。SHA1、SHA256和尤其是MD5都不够安全。 - tadman
bcrypt 不是唯一的方法。还有 scrypt(使用更多内存 - 这是一件好事)和 PBKDF2(类似于 bcrypt,但不太好)。 - Brendan Long

5

您应该使用 bcrypt 来哈希您的密码,它专门为哈希密码而设计。

用于密码的哈希函数应该是 慢速的(需要一些计算时间)。大多数哈希算法如 SHA-1 和 MD5 或者甚至 SHA-256 都是为了速度而设计的,但这使它成为暴力攻击的易受攻击目标。一个现成的 GPU 能够每秒计算约 8 十亿个 MD5 哈希值!

不要害怕使用 bcrypt!它不仅适用于高安全性的网站,而且使用它可以像使用 md5 哈希一样简单。建议使用一个成熟的库,如phpass,如果您想了解如何实现它,您可以阅读这篇文章,我在其中尝试解释了最重要的几点。

更新:

当前的 PHP 版本提供了 password_hash()password_verify() 函数来处理密码。使用它们像这样:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

以防有人想知道--bcrypt在一般意义上并不慢(如果您愿意,它可以每秒处理数百或数千个密码)。重要的是它不像MD5或SHA1那样快(它们每秒可以处理数亿个密码)。普通人没有必要每秒处理数亿个密码,但攻击者需要。 - Brendan Long
1
@Brendan Long - 确实,不同之处在于它提供了一个成本因素,该因素确定要执行多少次哈希迭代。将成本因素增加1会使所需时间翻倍,并使算法适应未来(因此更快的)硬件。 - martinstoeckli

2

我们使用Blowfish算法的crypt函数:

// Hash our password
$hashed = crypt($plain_text_password, '$2a$08$' . substr(hash('whirlpool', microtime()), rand(0, 105), 22));

// Validate a password
if (crypt($plain_text_password, $hashed) == $hashed)) {
    // Valid password
}

盐前缀$2a$(请参阅文档)指示crypt使用Blowfish算法。假设底层操作系统的crypt(3)实现支持它,您可以"免费"获得它。


我真的不明白这部分代码在做什么:. substr(hash('whirlpool', microtime()), rand(0, 105), 22) - Brendan Long
它使用“whirlpool”算法根据当前时间生成128个字符的哈希值,然后从中提取22个字符,并将它们附加到传递给crypt的盐。 - Sean Bright
每次调用rand(),你的应用程序就会更加安全,显然。 微笑 - Sean Bright
似乎如果你只需要盐,那么简单(而且更快)的方法就是获取22个随机数据字符。 - Brendan Long

-3

md5\sha1 + 独特的盐 = 最佳方式

不要过于多疑。


md5\sha1 + 独特盐值 比你自己制作的自行车更好 - MrSil
不,它太快且复杂了。使用bcrypt - Brendan Long
他在询问md5\sha1,而不是其他函数。我在我的Rails应用中使用bcrypt,在PHP中使用md5\sha1。 - MrSil
2
语言的选择与此无关。MD5和SHA1不是为密码散列而设计的(更具体地说,它们不是密钥派生函数)。既然存在安全的函数,为什么要使用不安全的函数呢? - Brendan Long

-5

你可以查找很多加密代码或者像这样混合使用它们:

sha1(md5(sha1($pw)));

我发现这没有必要,所以我使用的是SHA512 hash("sha512",$pw);


不行,请不要发布这样误导性的答案。 - tadman
这并不一定是一个坏主意,但在执行之前,你应该了解其含义。通过链接哈希函数并不会自动提高安全性。 - Brendan Long

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接