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

Posted

技术标签:

【中文标题】在存储到数据库之前加密密码?【英文标题】:Encrypt password before storing in database? 【发布时间】:2011-04-28 06:06:02 【问题描述】:

我的 iPhone 应用程序通过 php 脚本 user.php 将密码传递到数据库。

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

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

如何在将其插入我的数据库之前对其进行加密?我已经阅读了一些关于不同技术的信息,但正在寻找管理它的最佳方法。

谢谢大家。

【问题讨论】:

不相关:使用正确的输入转义,不要依赖str_replace 过滤掉所有撇号 它来自一个 iPhone 应用,通过 URL 传递给脚本。 另见 Openwall 的 Portable PHP password hashing framework (PHPass)。它强化了对用户密码的一些常见攻击。 【参考方案1】:

最基本的:用 MD5 或 SHA1 散列

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

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

最近我也开始存储散列的用户名,所以登录尝试只使用散列数据进行比较是安全的。

你可以用额外的数据“加盐”散列,所以如果它们被泄露,它的值就找不到了(尝试用谷歌搜索一些简单的散列词)。即使用站点范围的字符串来改变标准散列,如@987654323 @ 或者更高级的东西。

【讨论】:

@Chris 作为记录,散列是一种加密形式(尽管是单向的)。无论如何,MD5 绝不应该用于存储密码。使用今天的彩虹表,它和纯文本一样好。 从来没有说过散列不是一种加密形式,我只是说 md5 不是用于加密的。那么您为什么建议使用 md5 来“加密” OP 的密码。在使用 md5 进行密码加密来创建另一个具有复杂安全感的用户之前,至少在您的回答中解释这一点。 @Chris 你不想加密密码,你想散列它们。我正在编辑以添加盐渍,从而消除了彩虹表漏洞……尽管我仍然认为,如果有人进入您的数据库以获取哈希值,那么任何加密都无法拯救您。我不会“加密”密码,因为我不想要它们,也不希望有办法逆转它们。 每个密码/用户加盐是一个更好的主意。 我对 SHA1 散列很满意。这不是银行系统,只是一个论坛。如果有人真的想入侵并获取密码,他们无能为力。我正在添加散列以提供一点额外的安全性。【参考方案2】:

使用 php 的 crypt 库。 Md5 不是加密,是散列。

另外,加盐你的密码。 Why?

This answer Another good answer

【讨论】:

【参考方案3】:

使用crypt 和一些盐。比如

$user = strip_tags(substr($_REQUEST['user'],0,32));
$plain_pw = strip_tags(substr($_REQUEST['pass'],0,32));

$password = crypt(md5($plain_pw),md5($user));

如http://www.ibm.com/developerworks/opensource/library/os-php-encrypt/

【讨论】:

【参考方案4】:

虽然下面的答案在技术上仍然是正确的,但 php 对要使用的散列算法有新的建议。 Their recommendation,从 php >= 5.5.0 开始,是使用 password_hashpassword_verify 函数来散列和验证散列密码。作为一个额外的好处,这些函数会自动包含一个个性化的盐作为返回的哈希的一部分,所以你不需要明确地担心这一点。


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

有一件事,让它更安全一点是向散列添加盐并再次运行散列函数。这使得恶意生成密码哈希变得更加困难,因为盐值仅在服务器端处理。示例: $pass = sha1(sha1($_REQUEST['pass']).sha1("mySalt@$#(%"));

【讨论】:

这不是合适的盐。对于应用程序的每个用户来说,盐并不相同。相反,它是特定于用户的。 我用过这个。它正在工作,不需要非常神秘。【参考方案5】:

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

$password = sha1($password);

它也非常安全。尽管它的完整性开始下降,但将此功能升级到 SHA-256(非常安全)相当容易。

【讨论】:

SHA1 太快了。请参阅我的答案中的链接。 @middus 肯定是太快了,但是比MD5多占用30%的空间,所以至少表更大了。此外,如果有人对您的数据库有足够的访问权限来收集散列密码,那么他们很可能会窃取大量其他未加密的信息。 SHA1 并不“出色”,但它可以在 95% 的情况下使用。【参考方案6】:

要了解为什么 md5、sha1 和他们的快速朋友可能不是一个好主意,您应该阅读 Thomas Ptacek 的帖子Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes。要点:

最后,我们了解到,如果我们想 安全地存储密码我们有三个 合理的选择:PHK的MD5方案, Provos-Maziere 的 Bcrypt 方案,以及 建议零售价。我们了解到正确的 选择是 Bcrypt。

注意:它是 PHK,而不是 php。

【讨论】:

【参考方案7】:

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

$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

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

【讨论】:

以上是关于在存储到数据库之前加密密码?的主要内容,如果未能解决你的问题,请参考以下文章

第五章:shiro密码加密

shrio 加密/编码

贝宝数据在存储之前是不是应该加密?

密码加密并存储在数据库中

如何调用HashPassword并将用户密码存储到数据库?

散列或加密或两者都存储用户的密码? C# Winforms [关闭]