tags:

views:

643

answers:

7

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.

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.

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);
+21  A: 

Please, please for the sake of your users do not store their passwords in any reversible 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.

No website 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 (SHA, MD5, etc) 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

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.

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:

Rex M
@anonymous - Why the DV?
Rex M
False: "exactly as secure as if you didn't encode it at all"
Joe Philllips
@d03boy security by obscurity is the same as no security at all. In a self-contained system like a website, all of the necessary parts to reverse data, no matter how obfuscated, must necessarily be present. So if an attacker gains access to the system, the attacker has access to all the parts.
Rex M
Don't use MD5 or SHA-0, or SHA-1, they are all dead. Please, let us only recommend and use SHA-2 or above.
Noon Silk
@silky can you point to any documentation where those algorithms are demonstrably broken for passwords? To my knowledge they are only breakable for message digest schemes.
Rex M
It is not exactly the same. It may be similar. And I'm not the one that DV you
Joe Philllips
@d03boy You are technically correct but I think you may be splitting hairs. Especially in a case like this, simply getting developers to use non-reversible hashes doesn't require a great deal of nuance. We can talk about things in absolutes - they are either vulnerable to x or they are not.
Rex M
Rex: They're broken for verifying that X = X therefore H(X) = H(X) exlusively. But more importantly, a broken hash *ALWAYS* gets more broken, not less, and there is *absolutely no reason* for people to stick to MD5. I am personally stunned that people try and learn what is wrong with MD5 and then go to great lengths to show as to why it doesn't affect them. Better to leave that to the crypto experts, and just move on to a safe hash (SHA-2).
Noon Silk
Um, I wrote my message slightly wrong, but I hope you get the idea.
Noon Silk
@silky You are totally right that cryptography should be left to the experts. I often say that too. However, the experts are actually saying this: MD5 is broken for verifying X != Y because if X is known, Y can be constructed such that H(Y) = H(X). That problem does not apply to passwords. If someone were to want to use MD5 for cert validation or what-have-you, I would say stay away! But all the popular hashing schemes, properly salted, still work for passwords.
Rex M
Agree with d03boy, obscurity can play a role but I wouldn't rely on it exclusively. The key is not to store passwords in the DB in reversible format. Sending a temp password in email is probably fine for most services. Better if it expires. Better if you send an expiring link to choose a new password. Never send a user-generated password in email. A lot of the security "experts" are way to extreme in my opinion, which really compromises usability.
pbreitenbach
Rex: But if it's shown you can force a collision with plaintext chars, instead of non-printables, you may be screwed. It's better to call MD5 and SHA <= 1 dead. There is no reason to use them. Why would you recommend MD5 over SHA-2? Speed? Probably not, size? Doubtful, but if so, just take the first N bytes. There is no reason to keep using MD5. Let it die.
Noon Silk
@silky I would never recommend them over SHA2. I just can't say the alternatives don't work for passwords because they do.
Rex M
@silky I cannot even find sha-2 is it not a default thing in PHP?
jasondavis
Rex: I really think that's a mistake. @jasondavis: Sorry, I don't know anything about PHP, but check out : http://www.linuxpros.org/faqs/sha2-hashing-in-php/
Noon Silk
Rex: You may have seen this: https://documents.epfl.ch/users/l/le/lenstra/public/papers/Crypto09nonanom.pdf, but you may also be interested in: http://www.di.ens.fr/~bouillaguet/pub/SAC2009.pdf. My summary: Attacks on MD5 get worse over time. Stop using it.
Noon Silk
thanks, this whole thread has been very helpful, I learned a lot
jasondavis
+6  A: 

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.

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...)

hash('sha256', 'The quick brown fox jumped over the lazy dog.');
Joe Philllips
I am trying to find sha2, it does not seem to be on my php
jasondavis
Updated with sha-2 info
Joe Philllips
+8  A: 

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 hash of 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 salt your 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.

Ben S
I see so if I were to take a user submitted password and add there userid number which never changes to there password, then encrypt that string, that would be a salted password?
jasondavis
@jasondavis hash, don't encrypt
Rex M
+4  A: 

Base64Encode offer no security, because anybody can reverse it easily.

If you absolutely need 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.

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

Laurent Bourgault-Roy
A: 

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.

$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:

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

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

bucabay
Had to DV for the poor demonstration of SQL
Joe Philllips
Whats poor about that SQL?
bucabay
+4  A: 

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

  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.
Greg Hewgill
A: 

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

Jeff
I think, even more preferably, you would want SHA2
Joe Philllips
Despite concerns that SHA1 has a mathematical flaw which can result in easier to find collisions, including a salt will prevent such an occurrence.Langauges such as PHP don't support SHA2 in the standard library, so SHA1 is a very suitable alternative.
Lachlan McDonald