encrypt/hash the user's password into database - php

For user's password entered in a form before post, I simply just do
<?php
$pass=crypt($_POST['memberpwd']);
?>
But how can I later get the plaintext of that password in case the user may request ? Thank you.
EDIT: I found How can I encrypt password data in a database using PHP? and http://www.securityfocus.com/blogs/262, but I would just want to learn about this at a more basic level to understand the ways as to how it actually works.

Always store a password in a database using only a hash of (the pasword and a randomly generated salt) (googling for these terms combined with PHP should yield some useful results).
You never restore a plaintext version of the password, you provide means for the user to choose a new password after the user clicks on a unique referral url you only send out by email automatically on request.
(Very basic security).
EDIT:
I'll explain why you need the salt. Suppose someone compromised your database and has the user table with simple (e.g. MD5) password hashes. He (or she) can now simply launch a dictionary attack against the whole table with simple password combinations (e.g. select * from users where pw_hash = ...). If you use a randomly generated (but stored) salt to be used in the hashing of the password, this brute forcing attack gets exponentially harder to exploit.

The first thing to understand is exactly what crypt() does. Start off by reading this: http://php.net/manual/en/function.crypt.php
Essentially, crypt() is a hashing function. To be more exact, it is a one-way hashing function. As such you aren't going to be able to recover the password from it.
In today's world when a user has "forgotten" their password the best way of handling it is to create a new password, store that and email it to them.
By doing this you are ensuring that if they used the same password for multiple services you aren't inadvertently exposing those other services to nefarious people. Second, if it isn't the original user requesting the password, the next time they try to log in they'll notice their password doesn't work anymore.

Look at my answer to a related question.
Basically, you never ever ever store plaintext passwords. Databases can be compromised and most users use a universal password, which will allow the attacked to have access to tons of data. And it will be your fault (to some extent).
Hashing (in your case) works on this principle:
if hash(session.password) == database.hashed_password:
# You can safely assume session.password == database.password.
# Notice that I don't store database.password, but instead store:
#
# database.hashed_password = hash(register.password)
#
# when the user registers. That way nobody will ever know the password.
You can also use salts to make your hashes more secure. The same principle holds:
if hash(session.password + 'imasalt') == database.hashed_password_with_salt:
# Same as above.

Common practice is to use a one-way hash algorithm like SHA (and MD5 in the past). These cannot be reversed. If your user need to recover a password, the system usually resets it and tell the user the new password.
If you want two-way encryption (highly discouraged to store passwords) then your application will need to keep a secret (or have the user provide it).
Take a look at mcrypt http://php.net/manual/en/book.mcrypt.php

You don't. If they've forgotten their password, you should reset it and send them an email to create a new one, or something along those lines. Storing passwords in a way that means they can be decrypted and retrieved is very insecure and could, possibly, be illegal in some countries (I'm not a lawyer).

Related

Actual password visualisation in SQL table when using sha256

I am training to secure the login process.
I have used sha 256 in the sign_up.php:
$username= check_input($_POST['username']);
$password= check_input($_POST['password']);
//the password is encrypted in sha256
$secure_sign_up_password = hash('sha256', $password);
and then of course in my users table in my SQL database, I can read:
in the column 'login' the actual typed login
example: if somebody type 'michael', I will see 'Michael' in the SQL database
in the column 'password' the actual typed login
example: if somebody type 'fruit', I will see the hashed value like 'e8bfab56c53980cd014206c8da2f8c9b9708eaacc61' in the SQL database
My question is simple but maybe a bit naive (I'm a newbie): I thought that I could still be able to read the actual password somewhere in my database and that hashing was only made to protect the password from getting intercepted and read while it was being sent. I never know, somebody might ask me to send him his real password. But the only thing I can see is the 'hashed' one in the password column.
Is it made to be like this?
Is it possible to visualize also the real password?
If you would be able to "decode" those passwords, it wouldn't be a very safe system. Once someone gained access to your database - they would be able to gain access to every ones passwords without them knowing...
If you have ever forgotten a password for a site (and we all have - don't deny it!), you'll recall that they usually* don't simply send you your password (in plain text) as a reminder to your email - they'll give you the opportunity to reset it. This way (verifying usually through your email/phone number) they'll know that you are indeed the person who opened the account.
* If they send you your password in plain text that probably means they are storing it like that or in some other easily decrypted form. This site is most likely not as secure as they would like to think...
If you are interested in leaving yourself a "backdoor" of sorts to be able to access any of your users accounts, what you might think of doing is having a special login form from inside your administrator account, that allows you to use the encoded password to log in. That means that you simply leave out the hash('sha256', $password) and pass the $password already encoded (which you extract from your database). It's a bit hacky, and if you already have an administrator account then there wouldn't be much use to be able to log in as a different user because you are already all powerful!
This is by design. Nobody should know what my password is, except for me. Even you as a (insert fancy title here) should not know my password. If I forget it, that's my problem, but your site should offer me a way to reset it. Then when I reset, your site should store the hash once again. The plain-text password should never be stored anywhere.
Never never never hold password in open format in database. If someone find exploit in system, he will be able to make any sql query and get users passwords. And hacker will be able to login into system as user, because he knows username and password
If user want restore password, make functionality for regenerating password. Never store password in plain text.
SHA256 is hash function. Mathematically it means - data can be "hashed" only in one way. I mean, that from hash you cannot restore data. You can read this http://en.wikipedia.org/wiki/Hash_function about hash functions and this about http://en.wikipedia.org/wiki/Sha256 sha256
Result: If someone crack you database and get username and password, he is unable to login into system. Because hacker have only hash data and can't get exactly password for login.
As i mentioned before, hash function can be "hash" data only in one way. But some hackers build VERY big data massive for some predefined algorithms. I mean, that they build hash tables for passwords. Such hash tables looks something like this:
password hash
------------------
a some_hash1
b some_hash2
... .....
qwerty some_hash3
some_data some_hash3 -- yes, data can have collisions. See wiki about hash functions
And if hacker hacked you database and have such table, he able to restore password. For example, hacker get for admin user hash "some_hash3", then hacker search such hash in hash table, find that hash "some_hash3" have password "qwerty" and "some_data" and hacker will try to login with such passwords.
Result: Use salt. For nowadays hackers have such tables for 6 symbols passwords. But you can "suck" them in very simple technic: When you store password in database, add to password some value (salt) and get from such value hash:
// somewhere in code, where creating/updating users password
$password = hash('sha256', $salt.$password);
and when you will check password, use the same logic
Thanks
sha256 hashes and other hashes are one way. See http://en.wikipedia.org/wiki/Cryptographic_hash_function. If you want to be able to decrypt what you write in the password fields in your database, you might want to use another approach.
Instead of creating a hash, you could encrypt with a key, that you do not share with your users. Look at http://www.php.net/manual/en/book.mcrypt.php. The key would be part of your code though, as it's symmetric encryption.
To do it really safe, try real PKI encryption (encrypt with a public key, decrypt with a private one). Look at php.net/manual/en/function.gnupg-encrypt.php or php.net/manual/en/book.openssl.php.
But as other here have said, such things are reasonably NOT done ;)

Database encryption - php/mysql

I have some doubts about the best way to do a database with passwords. I need encryption in the passwords, but if i use MD5 i can't recover the pass, isn't it?
And the base64 encoder ? it is secure? with this encryption the recover isn't more a problem.
Suggestions? what is the best way? e prefer a solution that permit to remember the old pass, and not define a new one password.
Thanks!!!
If anybody know a good tutorial about secure passwords in a database i really appreciate that
if i use MD5 i can't recover the pass,
isn't it?
Indeed, if you hash your password using md5 or sha1 (adding a salt is a good idea, btw), you will not be able to recover the password ; and that's the goal of doing so !
The idea is if anyone is able to take a look at your database (be it some evil doer, or one of your employees -- who can be an evil-doer), he will not be able to find any usefull password.
what is the best way? e prefer a solution that permit to
remember the old pass, and not define
a new one password.
The best way is to do the opposite of what you want : not allow one to get his old password -- and develop some way of generating a new password.
This way, you will ensure that no-one is able to get a dump of your logins and corresponding password ; which will make your service safer for your users (especially considering that many people use the same login/password couple of several websites).
MD5 is not used for encryption (which implies that it can be decrypted) but rather for message digestion/hashing. Base64 is also not encryption but rather encoding, which can be decoded with no effort.
There is usually little point in storing encrypted passwords in a database if they can be easily decrypted.
The secure approach is to store only hashes and compare submitted passwords to stored hashes after hashing them on the fly.
You should be doing something along the lines of:
$salt = 'some2%string!!here1';
$hash = sha1( $salt . $_POST['password'] );
to create a hash of the password. You store that hash in the database. When a user wants to log in, you take his submitted function, hash it using the same process, and compare to the hash in the database. If they match, the password is correct.
First off, there's a Significant Difference Between Hashing and Encryption. I suggest that you give that a read before going on...
Now, as to your exact question, there are a few ways to go about it.
Encrypt your passwords with a strong cipher so that you can decrypt them when necessary. A solution such as the one in this post may work for that. However, please note that this isn't a great idea, since if your system is ever compromised, all the passwords will be leaked (never a good idea). There are very few use-cases where it makes sense to store them encrypted, but if you absolutely must, please use a strong cryptographic encryption routine to do it...
Store your passwords using a strong one-way hashing method. No, md5($password) is not good enough. But neither is sha1($salt . $password). The first is trivial to lookup most passwords, and the second can be brute-forced in a reasonable amount of time by simple trial and error. Instead, stretch your passwords iteratively. The best way is to use the standard PBKDF2 function to generate a strong one-way key from the password.
As far as how to recover if the user forgets a password, don't worry about it. If the user forgets his password, create a new one and give that one to the user. It's the industry standard way of dealing with forgotten passwords (Heck, both Windows and Mac do it that way). You may think that you're doing your users a favor by sending it to them, but all you're doing is turning off anyone who has a clue about security from every using your application (and making a lot of people mad if you get compromised).
base64 isn't "encryption". It's intended to convert binary data into a format that's safe for transmission through potentially "broken" email systems that can't process 8-bit binary data properly. It's a best the equivalent of a cereal box decoder ring.
If you want encryption, there's AES, DES, and various other functions available. Problem is, if your code can decrypt the password, the it's trivial for an attacker to figure out how you do it, and/or subvert your code to do it for them.
Passwords should never be stored in a format where the plaintext can be retrieved. If a user forgets their password, you wipe out the old one, generate a new temporary one, and force them to change this temporary password to something else on first login.
You should not ever need to remember the user's password - to do so is a violation of their trust and presents a security hole.
Normally you will hash the password with MD5 (these days it's better to use SHA-2), and when the user submits their password to try and log in, hash that password as well, and see if the hashes are a match.
For added security, you can create a "salt" column to the database and generate a random salt when the password is first submitted. Add the salt to the beginning of the password, and then hash it. Store the hash of the salt+password, and the salt together. Now when the user submits his password to log in, you would combine it with the salt, hash it, and check if the hash is a match.
The salt ensures that if multiple users have the same password (chances are they do), their password hashes will not be identical.
If the user forgets their password they will have to provide a new one, simply storing their password and sending it back to them when they forget is bad practice and a sign to the user that you aren't handling their privacy very well.
As mentioned, use a hash instead of encryption when saving passwords. I generally don't use a random salt since this means an extra field in the DB so that you can authenticate the user. The simplest solution is to use the password as the salt as shown below. Easy to use and easy to authenticate.
$salt = $_POST['password'];
$hash = sha1( $salt . $_POST['password'] );
Stop now and read this. Then go find an open source library to do user authentication. I'm not a PHP dev, so I can't refer you to one, but I'm sure they exist. They'll have had the security holes found already.
Also, for passwords, you should be looking at bcrypt or similarly slow hash functions for passwords anyways, instead of using a fast hash algorithm like MD5 or SHA.

How to generate secure passwords for new users?

I have a list of students that are being added via a form inside the admin area. I'm trying to come up with a password generating solution for each addition that will be both secure and viewable from the admin panel (like below).
I need it to be viewable so that the admin will be able to print out the passwords and hand them out to the parents. But I also want them to be secure in case there's a database breach. Any ideas?
If you want the passwords to be viewable, they can never be really secure in case of a breach.
You may be interested in checking out the following Stack Overflow posts for further reading:
Difference between Hashing a Password and Encrypting it
How should I ethically approach user password storage for later plaintext retrieval?
Store passwords in 2 forms:
1) MF5/SHA1 hash for secure validation
2) AES encripted with master password. I.e. in order to view passwords you enter master password and bingo. In case of theft attacker would not get passwords that easy (but can bruteforce).
This is one of the few times I would say the software shouldn't be adjusted to the user(s). You're talking a major security risk here.
I would advice making some kind report generator to print passwords that creates (generates / salts and hashes and saves) them on the fly for printing. With this, you could generate the letters to be send as well. Makes the process mostly automated and a person would only have to send them to the printer (if that's even necessary).
Good luck.
You should not do this.
Generate a one-time password that can be used (and could also be stored in clear text) to set a new password via web.
As soon as the passwords are printed, they can be easily accessed by others, so it does not matter at all if you store them encrypted or not.
You can have one XOR the other.
If the passwords are to be secure, you mustn't store them in the database (store some_hash(per_user_salt + password) and compare that on login (as #Daniel Vassallo says)
If the passwords are to be viewable, then you must provide some way to get to the passwords - and if there is one, it can be abused (e.g. passwords stolen). If you decide that you absolutely, positively need to do this, encrypt the passwords in your application before storing them to the database. This won't shield you from all threats, but at least the passwords won't be readable if someone "only" steals your database.
Others have had the right idea, but were missing an essential step. You should use asymmetric encryption and store a public-key encrypted form of the password + salt.
To verify a password, take the proffered password, combine it with the salt, use the public key to encrypt the combination, and compare it with the stored value.
To retrieve the password, use the private key (kept secure, i.e. on another isolated machine) to decrypt the password + salt and throw away the salt.
Cons: asymmetric encryption can be expensive, computationally, but passwords tend to be short.
You could combine this with other ideas above (i.e. also store a salted hash), and you should pad the password so that the length of the encrypted text doesn't leak the password length.

PHP:How to send the original password to the user when he clicks forgot password which is encrypted by using md5?

I am using md5 to encrypt the passwords in my project.
When user clicks on forgot password and submits his email,I have to send His password to him.
But the password is encrypted using md5.Generating new password should not do.Because In this project admin can see all the details of the user. So i have to show the original password to Admin. So The initial password is very important. SO how can i decrypt the password or any other way to send him original password?
Thanks in advance...
Hashes are not designed to be decrypted, which is why they're often referred to as "one-way hashes" instead of just hashes.
Instead, either...
Generate a new password, hash that, store the new password hash in place of the old one, and email the newly generated password to the user.
Generate a new password, hash it, store it in a field for temporary passwords, and then when the user logs in with that password, prompt them to enter a permanent new password.
Generate a nonce, store it in a field for the nonce, and email the user a link with that nonce which will give them access to a page to enter a new password.
The third option is probably the best all around, since it doesn't leave an actual password (temporary or not) in plain view to someone reading the user's email, and since it utilizes a nonce, once it has been used it can't be used again by a malicious user.
The reason hashing is used for passwords is specifically to prevent them from being stored in a form where a malicious user could determine the password simply by looking at the database.
Edit:
"So i have to show the original password to Admin."
If you are hashing the password, this is not possible. In general, it is actually a bad idea to allow administrators to see users' passwords, because a large percentage of users tend to utilize the same password for multiple things, and the administrator of one thing (say, a company network) is probably not the administrator of many other things (say, a user's online banking system).
MD5 is not an encryption algorithm, it is a hashing algorithm. The two are not the same; encryption is designed to be reversible (hence the complementary term "decryption"), whereas hashing is designed to be one-way only.
You can't. The reason cryptographic hashes[1] are referred to as "non-reversible" is that they can't be reversed. Which is the entire point of using them for password storage - it means that, if a Bad Guy gets his hands on the password database, he can't just reverse the hash to find out what all the passwords are.
I see from your edit that your intent is to display the user's password to the admin user(s) rather than for password recovery by the user himself. This is a Very Bad Idea. Many users attempt to ease the burden of remembering passwords by using the same password for multiple systems, which means that displaying their password in your system has a high probability of compromising their accounts on other systems.
True story: Back in 2000, I took a job at a startup that produced voicemail systems. To introduce me to the product on my first day, the IT director had me create a voicemail account, which I did, then he brought it up in the admin interface. I just about died when I saw my voicemail PIN displayed on the screen for all to see. Partly because it was shockingly bad security practice, but mostly because, even though he didn't know it, he now knew the PIN for my ATM card. That's just bad, bad, bad all around. Don't do that.
[1] MD5 is a hashing algorithm, not an encryption algorithm. The key difference between the two is that, for any given hashing algorithm, there are an infinite number of inputs which will produce the same output (which is why it's not reversible), while encryption has a one-to-one correspondence of input to output.
If the password has been hashed then you'll probably have to create a random password and send that to the user. Then, once they've logged in, take them to the Change Password screen so they can change their password to something more memorable.
One particular purpose (among others) of a hash value is that it's irreversible, if it works perfectly.
The most common way for a "forgot password" functionality is, to generate a new password and tell your user to change it as soon as possible.
Just adding this as a sidenote:
While you cannot "unhash" the MD5 hash, you can look it up in a Rainbow table. That might allow you to send the original plaintext password to the user. I am not suggesting to do that though, because it's just a waste of resources compared to just creating a new password and sending that to the user instead.
From http://en.wikipedia.org/wiki/Rainbow_table:
A rainbow table is a lookup table offering a time-memory tradeoff used in recovering the plaintext password from a password hash generated by a hash function, often a cryptographic hash function. A common application is to make attacks against hashed passwords feasible. A salt is often employed with hashed passwords to make this attack more difficult, often infeasible.
Also see the comments below for additional notes.

Best way to encode passwords in PHP

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);
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 (bcrypt or 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
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:
Difference between Hashing a Password and Encrypting it
Why is challenge-response approach a poor solution for forgotten passwords?
Non-random salt for password hashes
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.
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.');
An absolute must-read on this topic is Jeff's own You're Probably Storing Passwords Incorrectly. Here's the executive summary:
Do not invent your own "clever" password storage scheme.
Never store passwords as plaintext.
Add a long, unique random salt to each password you store.
Use a cryptographically secure hash.
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
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.
You will want to use a hash(preferably sha1) with "salt"
You can do the hashing on the server when authenticating in one quick query:
SELECT * FROM user WHERE password = MD5(CONCAT(?, salt));

Categories