在PHP中编码密码的最佳方法

时间:2009-09-08 02:04:47

标签: php passwords

我目前正在使用,
base64_encode()来编码用户的密码,这很有效,因为它允许我只使用 base64decode()将密码解码为单词并发送到那里的电子邮件丢失密码。

我一直在阅读密码,很多人似乎都说你应该使用 sha1()来编码密码。我全都是为了提高系统的安全性,但如果我转换为使用 shal(),那么我将无法向用户发送丢失的密码。

你用什么?你能给我一些建议吗?是否有办法解密可读密码以通过电子邮件发送给用户?

当我输入这个问题时,我只是记得有些论坛在请求时没有给你发密码,而是发送一个特殊的链接来重新设置你的密码,我猜这是因为他们无法解密你的密码也许?

//what I use now
$password_encoded = base64_encode($password);

//what I am considering using
$password_encoded = sha1($password);

8 个答案:

答案 0 :(得分:43)

请为了您的用户请不要以任何可逆格式存储密码!如果它是Base64编码或triple-DES 168-bit encryption - 如果它是可逆的并不重要,它就像你根本不编码一样安全

没有网站有兴趣保护自己或其用户(或有舔感)将通过电子邮件向用户发送密码。我们唯一可以做的就是远程安全,即向用户发送一封电子邮件,其中包含一个独特的一次性链接,可让他们设置新密码。

  • 存储已bcrypt
  • 密码的哈希值(PBKDF2salted
  • 一旦您将其密码丢失,请立即丢弃原始密码。从记忆中消除它。
  • 始终要求用户通过SSL渠道创建自己的新密码

试图与其他任何东西相处只是疏忽。让我们使用安全讨论中常用的场景:

用户Frederic的电子邮件遭到入侵。这可能是因为他的计算机已解锁或使用弱密码。无论如何,未经授权的人都可以访问他的消息。理想情况下,这只不过是陌生人阅读的一些令人尴尬的情书。不幸的是,未经授权的人发现论坛将以纯文本形式向Frederic的密码发送电子邮件。与大多数用户一样,Frederic对所有内容使用相同的密码,包括他的网上银行。他的用户名列在他银行的电子邮件中。现在情况非常不幸。

用户在与您建立基于凭据的关系时会信任您。信任的一部分是你将这些凭证保存为你和他们之间的安全秘密。

  

相关

     

许多周围的问题和想法在SO上得到了很好的回答:

     

答案 1 :(得分:10)

作为管理员,您实际上不需要回忆用户的密码。您只需要知道他们曾经提交的字符串是否与另一个字符串相同。

如果用户忘记密码,则无需告知他们的旧密码,只需让他们提供新密码即可。

由于您不需要知道实际密码,因此使用crytographic hash单词似乎是一种安全存储方式。但是,已经制作了大量预先计算的字符串表,可以轻松地对其原始字符串进行反向查找。这些被称为rainbow tables

为了避免轻松查找预先计算的字符串,您应该在对其进行散列之前salt密码。 salt可以是他们的用户名前缀,或者他们的用户ID是后缀的,无论您在用户身上获得的永久性信息,您都可以在身份验证期间轻松添加到密码中。

答案 2 :(得分:6)

您应该让用户重置密码,但永远不要检索他们的密码。这就是为什么你想要使用单向散列(SHA2)而不是一种允许你解码它的加密形式。

想象一下,如果您打开电子邮件。我可以简单地请求检索一些网站的密码,删除电子邮件,你永远不会知道。另一方面,如果您要求我重置密码,帐户密码将会改变,并且所有者显然会意识到出现了问题。 (这是一个愚蠢的场景,但这个概念很重要)

通过尝试所有可能的单词组合(或使用彩虹表),可以“反转”哈希值,直到产生匹配的哈希值。避免这种情况的一种方法是使用salt附加/前置提供的密码,使其成为一个非常长且不可预测的字符串。 salt应该是个人帐户唯一的唯一数据字符串。

在PHP中没有SHA2功能。 SHA-2是一系列哈希算法,(SHA-256,SHA-384,SHA-512等......)

hash('sha256', 'The quick brown fox jumped over the lazy dog.');

答案 3 :(得分:5)

关于这个主题的绝对必读是Jeff自己的You're Probably Storing Passwords Incorrectly。这是执行摘要:

  1. 不要发明自己的“聪明”密码存储方案。
  2. 绝不将密码存储为纯文本。
  3. 为您存储的每个密码添加一个长而独特的随机盐。
  4. 使用加密安全哈希。

答案 4 :(得分:4)

Base64Encode提供安全性,因为任何人都可以轻松地撤消它。

如果您绝对需要撤销密码,一个好方法是使用机密问题,并将答案用作加密密钥。一旦密码被加密,你就会把答案扔掉(你不存储它)。当您需要验证他是否输入正确的密码时,您还可以使用标准的sha1加密。如果用户想要密码,则输入其秘密问题的答案,然后使用该密码恢复密码并将其发回给他。

它不像基于散列的加密那么安全,但如果你需要发回密码,这是一个很好的妥协。

您可能需要查看php http://ca3.php.net/mcrypt

的mcrypt库

答案 5 :(得分:1)

我始终只删除任何通过电子邮件发送给我密码的网站。我花了太多的精力和时间来记忆长的随机密码,以便以纯文本形式发送给我。

使用sha1()或更高版本的不可逆哈希来标识密码。验证用户密码时,检索散列,并将其与验证期间提供的密码的散列进行比较。如果它们匹配,则用户在合理标准内是真实的。

$user = "joe";
$password = 'password';

$saved_hash = DB::Query("select hash from users where username = ".quote($user)." LIMIT 1");

if (sha256($password) == $saved_hash) User::authenticated();

永远不要在电子邮件中发送密码。发送一个唯一的,不可预测的生成密钥,例如PHP:

$key = sha256(time().rand().$secret_seed);

将此密钥发送给客户端,一次性使用,以设置新密码。

答案 6 :(得分:0)

您需要使用带有“salt”的哈希(最好是sha1)

答案 7 :(得分:0)

在一个快速查询中进行身份验证时,您可以在服务器上进行散列处理:

SELECT * FROM user WHERE password = MD5(CONCAT(?, salt));