在存储到数据库之前加密密码?

6

我有一个密码从我的iPhone应用程序通过php脚本user.php传递到数据库中。

变量$pass由以下内容填充:

$pass = str_replace("'", "", $_REQUEST['pass']);

在将其插入数据库之前,我该如何加密它?我已经了解了一些不同的技术,但正在寻找最好的管理方式。

感谢大家。


请使用适当的输入转义,不要依赖于“str_replace”来过滤所有的撇号。 - knittl
它来自iPhone应用程序,通过URL传递到脚本。 - BigMike
还可以查看Openwall的Portable PHP密码哈希框架(PHPass)。它经过加固,能够抵御许多常见的用户密码攻击。 - jww
7个回答

7

7

虽然下面的答案在技术上仍然是正确的,但php已经提出了关于使用哈希算法的新建议。他们的建议,自php>= 5.5.0以来,是使用password_hashpassword_verify函数对密码进行哈希和验证。作为附加好处,这些函数会自动包含返回哈希的个性化salt,因此您不需要明确担心它。


如果您不关心从数据库加密值中检索实际密码的值,则可以对其运行单向哈希算法(例如sha1)。此函数将返回特定长度的字符串(哈希),不能用于查找原始字符串(理论上)。可能两个不同的字符串会创建相同的哈希(称为碰撞),但这对于密码不应该是问题。
示例: $pass = sha1($_REQUEST['pass']);

为了增加安全性,可以向哈希值添加盐并再次运行哈希函数。这样做可以使恶意生成密码哈希更加困难,因为盐值仅在服务器端处理。
示例: $pass = sha1(sha1($_REQUEST['pass']).sha1("mySalt@$#(%"));


1
这不是一个适当的盐值。每个应用程序用户的盐值都不相同,因此它是用户特定的。 - middus
我用了这个。它能正常工作,而且不需要过于复杂的加密。 - BigMike

2

首先,您应该创建一个随机的用户盐值。然后您应该将其和密码哈希值存储在数据库中。

$salt = md5(unique_id().mt_rand().microtime());
$pass = sha1($salt.$_REQUEST['pass']);

将$salt和$pass保存在数据库中。然后当他们登录时,您查找他们的行并检查哈希值:

$user = query('SELECT * FROM `user` WHERE username = ?', array($_REQUEST['username']));

if($user)
{
    // If the password they give maches
    if($user->pass === sha1($user->salt. $_REQUEST['pass']))
    {
        // login
    }
    else
    {
        // bad password
    }
}
else
{
    // user not found
}

为每个帐户创建一个用户盐,可以确保彩虹表无用,任何入侵您服务器的人都必须对每个密码进行暴力破解。

1

最基本的方式:使用MD5或SHA1进行哈希处理

$newpass = md5($_REQUEST['pass']);

或者

$newpass = sha1($_REQUEST['pass']);

最近我开始将用户名也进行哈希存储,这样登录尝试就可以使用仅哈希数据进行比较来保证安全。

您可以使用额外的数据对哈希值进行“盐”处理,以便在泄露时无法找到其价值(尝试谷歌一些简单的哈希词语)...例如,使用一个站点范围内的字符串来改变标准哈希,如md5("mySiteSalt!!" . $_REQUEST['pass']);或更高级的方法。


1
就记录而言,哈希是一种加密形式(尽管是单向的)。无论如何,MD5绝不能用于存储密码。随着今天的彩虹表,它与明文一样不安全。 - mattbasta
从来没有说过哈希不是加密的一种形式,我只是说md5不适用于加密。那么为什么你建议使用md5来“加密”OP的密码呢?在创建另一个使用md5进行密码加密的安全感含糊的用户之前,请在你的回答中至少解释一下这个问题。 - Chris
@Chris,你不想加密密码,而是想要哈希它们。我正在编辑以添加盐,这可以消除彩虹表漏洞...尽管我仍然认为,如果有人进入您的数据库获取哈希值,任何加密都无法拯救您。我不会“加密”密码,因为我不想要它们,并且我不希望有一种方法可以将其反转。 - Fosco
1
一个每个密码/用户盐的想法更好。 - middus
我对仅使用SHA1哈希算法感到满意。这不是银行系统,只是一个论坛。如果有人真的想要黑入并获取密码,他们也无法做太多事情。我添加哈希算法只是为了提供一点额外的安全性。 - BigMike

1

0

在数据库中存储密码时,您应该使用SHA1进行哈希处理。这是最简单、最有效的存储密码的方法:

$password = sha1($password);

它也异常安全。虽然其完整性开始受到侵蚀,但将此函数升级为SHA-256(非常安全)相当容易。


SHA1太快了。请查看我的回答中的链接。 - middus
@middus 当然它速度确实太快了,但是它比MD5使用多30%的空间,至少表格更大。而且,如果某人有足够的访问权限来获取哈希密码,那么他们很可能可以窃取大量其他未加密的信息。SHA1并不是“完美”的,但在95%的情况下,它足以胜任。 - mattbasta

0

如果你想知道为什么 md5、sha1 及其快速的朋友可能不是一个好主意,你应该阅读 Thomas Ptacek 的文章Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes。要点如下:

最后,我们了解到,如果我们想安全地存储密码,我们有三个合理的选择:PHK 的 MD5 方案、Provos-Maziere 的 Bcrypt 方案和 SRP。我们了解到正确的选择是 Bcrypt。

注意:这里说的是 PHK,而不是 PHP。


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