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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1391613/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:22:35  来源:igfitidea点击:

Best way to encode passwords in PHP

phppasswords

提问by JasonDavis

I currently use,
base64_encode()to encode a user's password, this works well because it allows me to simply use base64decode()to decode the password to a word and send to there email if they lose there password.

我目前使用
base64_encode()对用户的密码进行编码,这很有效,因为它允许我简单地使用base64decode()将密码解码为一个单词,并在他们丢失密码时发送到那里的电子邮件。

I have been reading up on password though and a lot of people seem to say that you should use sha1()to encode a password. I am all for improving my system's security but if I convert to use shal()then I will not be able to send a user there lost password.

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

What do YOU use? Can you give me some advice? And is there a way to decod to a readable password to email a user?

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

As I typed this question I just remebered that some forums do not send you a password when requested but instead send a special link to re-set your password, I am guessing that this is because they are unable to decode your password maybe?

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

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

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

回答by Rex M

Please, please for the sake of your users do not store their passwords in anyreversible format! It doesn't matter if it's Base64 encoded or triple-DES 168-bit encryption- if it is reversible, it is exactly as secure as if you didn't encode it at all.

请,为了您的用户,请不要以任何可逆格式存储他们的密码!无论它是 Base64 编码还是三重 DES 168 位加密都没有关系——如果它是可逆的,那么它就像你根本没有编码一样安全

Nowebsite that has any interest in protecting itself or its users (or has a lick of sense) will send a user their password via e-mail. The only thing we can do that's even remotely close to secure is to send users an email with a unique, one-time-use link that lets them set a new password.

任何有兴趣保护自己或其用户(或有一点感觉)的网站都不会通过电子邮件将密码发送给用户。我们唯一能做的甚至是远离安全的事情就是向用户发送一封电子邮件,其中包含一个唯一的、一次性使用的链接,让他们可以设置新密码。

  • Store a hash (bcryptor PBKDF2) of the password which has been salted
  • Throw away the original password as soon as you've hashed it. Excise it from memory.
  • Always require the user to create their own new password over an SSL channel
  • 存储已加盐的密码的哈希(bcryptPBKDF2
  • 散列后立即丢弃原始密码。从内存中删除它。
  • 始终要求用户通过 SSL 通道创建自己的新密码

Trying to get by with anything else is honestly just negligence. Let's use a very common scenario used in security discussions:

老实说,试图应付其他任何事情只是疏忽。让我们使用安全讨论中使用的一个非常常见的场景:

User Frederic's email is compromised. This could be from leaving his computer unlocked or using a weak password. Regardless, an unauthorized person has access to his messages. Ideally, this would mean nothing more than some embarrassing love letters read by a stranger. Unfortunately, the unauthorized person discovers a forum will email Frederic's password in plain-text. Like most users, Frederic uses the same password for everything, including his online banking. His username is listed in an email from his bank. Now the situation is very unfortunate.

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

Users are placing trust in you when they create a credentials-based relationship with you. Part of that trust is that you will keep those credentials as a secure secret between you and them.

当用户与您建立基于凭据的关系时,他们就会信任您。这种信任的一部分是您将这些凭据作为您和他们之间的安全秘密。

Related

A lot of the surrounding issues and ideas have been answered very well on SO:

有关的

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

回答by Ben S

As an administrator, you never actually need to recall the password of a user. You simply need to know if a string they've once submitted, is identical to another.

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

If a user forgets their password, they don't need to be told their old password, you can simply have them provide a new one.

如果用户忘记了他们的密码,他们不需要被告知他们的旧密码,您只需让他们提供一个新密码即可。

Since you don't need to know the actual passwords, using a crytographic hashof the words would seem like a safe way to store them. However, large tables of pre-computed strings have been made to easily do a reverse-lookup of the hash back it's original string. These are called rainbow tables.

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

To avoid easy lookup of pre-computed string, you should saltyour passwords before hashing them. The salt can be their username prepended, or their user ID postfixed, whatever extra information you have on the user that is permanent that you can easily add to the password during authentication.

为了避免预先计算的字符串容易查找,您应该哈希之前您的密码。盐可以是他们的用户名,或者他们的用户 ID 后缀,无论您拥有关于用户的任何永久信息,您都可以在身份验证期间轻松添加到密码中。

回答by Joe Phillips

You should let a user RESET a password but never RETRIEVE their password. That is why you would want to use a one-way hash (SHA2) instead of a form of encryption that lets you decode it.

您应该让用户重置密码但永远不要检索他们的密码。这就是为什么您希望使用单向哈希 (SHA2) 而不是一种允许您对其进行解码的加密形式。

Imagine if you left your email open. I could simply request to retrieve your password for some website, delete the email, and you would never know. On the other hand, if you required me to reset the password instead, the account password would change and the owner would obviously realize that something is wrong. (This is a dumb scenario but the concept is what's important)

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

Hashes can be "reversed" by trying all possible combinations of words (or using rainbow tables) until a matching hash is produced. One way to avoid this is to append/prepend the provided password with a salt to make it a very long and unpredictable string. The salt should be a unique string of data unique to the individual's account.

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

In PHP there is no SHA2 functon. SHA-2 is a family of hash algorithms, (SHA-256, SHA-384, SHA-512, etc...)

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

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

回答by Greg Hewgill

An absolute must-read on this topic is Jeff's own You're Probably Storing Passwords Incorrectly. Here's the executive summary:

关于这个主题绝对必须阅读的是 Jeff 自己的你可能不正确地存储密码。以下是执行摘要:

  1. Do not invent your own "clever" password storage scheme.
  2. Never store passwords as plaintext.
  3. Add a long, unique random salt to each password you store.
  4. Use a cryptographically secure hash.
  1. 不要发明自己的“聪明”密码存储方案。
  2. 永远不要将密码存储为明文。
  3. 为您存储的每个密码添加一个长而独特的随机盐。
  4. 使用加密安全的哈希。

回答by Laurent Bourgault-Roy

Base64Encode offer nosecurity, because anybody can reverse it easily.

Base64Encode 不提供任何安全性,因为任何人都可以轻松逆转它。

If you absolutelyneed to reverse the password, a good way is to use a secret question, and to use the answer as an encryption key. Once the password is encrypted, you throw the answer away (you do not store it). You also use the standard sha1 encryption for the time when you need to verify that he enter the right password. If the user want its password, he enter the answer to its secret question, and you use that to restore the password and send it back to him.

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

It's not as secure as hash based encryption only, but if you need to send back the password it's a good compromise.

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

You may want to look at the mcrypt library for php http://ca3.php.net/mcrypt

您可能想查看 php http://ca3.php.net/mcrypt的 mcrypt 库

回答by bucabay

I always delete my account only any sites that emails me my password. I put too much effort and time into memorizing long random passwords to have it sent to me in plain text.

我总是只删除任何通过电子邮件发送我的密码的网站我的帐户。我花了太多的精力和时间来记住长长的随机密码以将它以纯文本形式发送给我。

Use sha1() or higher non-reversible hash to identify the password. When authenticating a user password, retrieve the hash, and compare it with the hash of the password supplied during authentication. If they match, then the user is authentic within reasonable standards.

使用 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();

Never, ever send passwords in email. Send a unique, non-predictable, generated key, such as in PHP:

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

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

Send this key to the client, for one time use, to set a new password.

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

回答by Jeff

You will want to use a hash(preferably sha1) with "salt"

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

回答by voteforpedro

You can do the hashing on the server when authenticating in one quick query:

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

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