Is there a simpler encryption/decryption hash algorithm out there? - php

I have read on this great forum and several other places how difficult, if not impossible to decrypt with md5.
Unfortunately, I used md5 to hash our users' passwords:
// hash to sanitize the input further
$password = md5($password);
Now, I am a bit of trouble because users who cannot remember their passwords, are not able to utilize our Recover password feature.
When they attempt to recover their password, they receive the encrypted password which is useless to them because they can't use it.
Given how difficulty, almost impossible it is to decrypt an md5 hash, is there a simpler encryption / decryption mechanism that someone could suggest that I try?
Pretty much in hot water now.

Unfortunately, I used md5 to has our users' passwords
How is that unfortunate? That's what you're supposed to do. User passwords should be obscured behind a 1-way hash and not recoverable by anybody. Not even by you as the system owner/administrator.
users who cannot remember their passwords, are not able to utilize our Recover password feature
There should be no such thing as a "recover password feature". It's called a "reset password feature". You can change a user's password administratively. But you should never ever be able to read it.
When they attempt to recover their password, they receive the encrypted password which is useless to them because they can't use it.
But attackers can use it. Which is why you shouldn't be sending it out to anybody in the first place.
is there a simpler encryption / decryption mechanism that someone could suggest that I try?
Is doesn't get much simpler than:
md5($password)
It's one function call. Five keystrokes. It's really simple to use. And since you're already using it, you're good.
Once you stop publishing your password hashes, you'll be all set on handling user passwords (at least as far as we know here). Keep up the great work! There are tons of services out there which don't properly obscure user passwords. Thank you for at least attempting it.
Note: As users have pointed out (users who are far more familiar with PHP these days than I am), while using md5() directly is a step in the right direction, it's not the best you could be doing.
Instead, take a look at PHP's built in password handling functionality. (Or, if you're using an older, pre-5.5 version of PHP, there's a compatibility pack which maintains the same functionality.) Jay Blanchard has written a handy article on its use here.
The concept is the same, obscuring user passwords by means of a one-way hash. But the tooling has evolved considerably.

Related

Should I encrypt my password after I hashed it? If so how to properly do it?

I am trying to get a better understanding on Hashing and Encryption, however I stumbled upon questions that I can't seem to find in Google because Google keep offering basic difference of Hashing and Encryption, which I already read.
More over a lot of people ask in StackOverflow which have no idea about the difference between encryption and hashing gets to the top of the SO's search engine. Which doesn't answer my questions, and didn't help me. So I wanted to make sure a few things about hashing a password and encrypting one.
Now let's say I wanted to secure a new registered user..
I need to filter it first. (Skipped because of unrelated)
After I get a 'safe' form of the password, I hash it.
$safePassword; // Already filled with safe password.
$hash = password_hash($safePassword,PASSWORD_ARGON2I);
Then insert it to database.
Now this is the where questions rises.
Do I still need to encrypt the hashed password?
If so, how do I securely encrypt the password? (I'm going to use AES)
AES_ENCRYPT(str, key_str);
Where str is the String that we wanted to encrypt and key_str is the encryption key.
Another question rises
How do I keep the key_str safe, so I can use it for further use (for authentication)?
You don't need to encrypt the password, just running it through your password hash, like you included in your question, is perfectly fine. Hashing is a one-way operation, so it is "impossible" to reverse the hash and get the original password.
Encrypting passwords after hashing them doesn't make things any less secure, it just doesn't really make things any more secure either. It also introduces more problems - where to keep the key?
Stick to just Argon2, anything further is unnecessary.
Now let's say I wanted to secure a new registered user..
I need to filter it first. (Skipped because of unrelated)
If by "filter", you mean somehow altering this password.... no! Not only do you not need to do this, you're actually causing yourself a real headache later on down the road, and reducing the security of the password.
Now this is the where questions rises.
Do I still need to encrypt the hashed password?
No. Hashing is a one-way function. You cannot recover the password from its hash. (You could use a rainbow table, which is effectively a list of passwords that result in certain hashes. That's what a proper salt helps prevent.)
There is nothing gained by encrypting this hash.
Another question rises
How do I keep the key_str safe, so I can use it for further use (for authentication)?
This is actually a key reason the encryption isn't useful. To use it, you would need to decrypt it, which means keeping the keys around in the same place as the hash data in the first place.

Password Database on PHP file

A quick question for you! This is my first WEB application...
Is it safe leaving the password visible in the PHP file or there is a way to protect/hide it?
Thank you
Davide
There exists different situations to store a password, which cannot be handled in the same manner.
The worst case for security is, when you need the password later in cleartext for another service. From your comment i can see that this is your situation, you need to store the database login credentials. There is not much you can do, but storing the password in a separate include file, and place it somwhere above the root directory.
A little better is the case, when your application needs to store a fix password only for verification. Then you can store a hash of the password, so even if somebody can read your code, he doesn't know the plaintext password. An example of this case is a protected directory with HTTP-auth.
The best case is when you have to store user passwords. Then one should absolutely calculate a hash of the password, so that nobody but the user ever knows (or can retrieve) the password. Recommended algorithms are BCrypt, PBKDF2 and SCrypt (see password_hash()). Never use MD5 or SHA-* because they are too fast and can be brute-forced too easily.
I included the three cases in the answer, because sooner or later surely you will stumble over the other cases as well.
No, it is not safe or a good practice to keep the password visible anywhere. Even you/developer should not know the password except the user.
Use hash for encrypting the password and sha256/sha512 is considered best algorithm for hashing.
No, You must always think about security. If passwords are stored in plain text, what happens if an attacker gains access to your database? He can easily read all of the users’ passwords. That’s why we use a technique called password hashing to prevent attackers from getting user passwords.
Use md5() php function to secure your password .
$password = md5($password);

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.

What are the best practices to encrypt passwords stored in MySql using PhP?

I am seeking advice on how to securely store passwords in MySQL using PHP.
Overlooking the limitations of PHP itself, I want to know more about salting, hashing, and encrypting these bad boys.
Obviously people will continue to use weak passwords unless forced to do otherwise, but it's how I am storing them that is important to me. My user's passwords are far more important to me than the database itself, and as such I want to keep them in such a way that it will be painstaking and monotonous for any script kiddie trying reverse. Obviously with due diligence just about anything can be defeated, but I wouldn't mind making this particularly bothersome.
There are two scenarios we are looking at.
The kiddie has a complete copy of the database.
The kiddie has a complete copy of the PHP used to craft the password, and the database.
Any and all advice on this topic is graciously appreciated.
Use bcrypt. If someone has the user table of your database, then they can use brute force/rainbow tables/etc to their heart's content. Even with salt, if you're using MD5 or some other fast-hashing algorithm (which aren't designed to solve this problem, by the way); it's just a matter of time before it can be cracked.
Any well-known and widely-supported hashing algorithm is going to have this same basic "flaw" (if you can call it that; it's really by definition). The difference is that bcrypt is slow as molasses when performing the hashing operation, rendering a brute force attack much less effective.
For an absolutely great discussion on the merits of bcrypt, the dangers of other approaches, and the difficulty of password security in general, read this thread. It has lots of comments by many people that are much more knowledgeable about this sort of thing than I am, and it should hopefully help you understand more of the issues at stake.
Assuming you're using username and password as authentication tokens you can safely store the following to ensure the data can't be compromised.
Username (in plaintext)
Salt (random string)
Salted Hash (sha1(username + salt + password))
Using the scheme, an attacker cannot use rainbow tables against you and the passwords are not recoverable by any (reasonable) means. (That is, as long as your attacker isn't the government)
Even though the attacker has the salt and hash pairs it's not possible to use rainbow tables because all the possible hashes will need to be computed anyway, using the salt that they've been given, so it's a brand new brute force attack for each user.
Even with the source code and attacker won't be able to get hold of the passwords because the strength/security is in the hashing algorithm, not your code.
Combine this with using bcrypt as per Donut's answer and you're really quite safe. That is:
Username (in plaintext)
Salt (random string)
Salted Hash (bcrypt(username + salt + password))
Taking advice from here, for added fun you can dynamically change your salt as well. For example, use different salts for usernames of different length, use the user's registration date as the salt. This makes it that even if someone DOES get to your database, they can't just re-generate the hash, they have to calculate a hash table for each salt that you used.
If your users are over the internet, OpenId would be one of your best options. http://openid.net/
If your users are on your network, can you do Integrated Security?
In other words.. do not store their passwords.
Usually "salted" passwords (like with bcrypt) mean that not the password itself is stored, but only something like
salt
hash(salt with password appended)
Now if the kiddie has your database (and of course, the code - there is no point in keeping the code secret), he/she can only guess passwords, calculate the salted hash, and compare. If the hash function is expensive (like bcrypt is), than guessing is expensive too.
It's simple
store(sha256("somesalt" + password));
And nobody will be able to reverse it :)
See also: https://stackoverflow.com/questions/3897434/password-security-sha1-sha256-or-sha512

Questions about salting passwords

Okay. Say for example that i set the salt for a password to "hello." Can't someone just look at the source code and discover the salt? If so, how would I hide it? Thanks.
Salts are are usually stored in plain text alongside the password hash. The main reason they are there is to make it more difficult to use precomputed rainbow tables and more difficult to perform a dictionary attack on all the passwords in the database.
You should also use a different randomly generated salt for each password, rather than a single salt for your entire application. This means that each password must be cracked separately.
First of all: Security is HARD. Don't try and do it yourself, because you will screw it up. Use a well-established library to handle user authentication.
Secondly, you seem to misunderstand the purpose of a salt. The salt is just there to prevent easy reversing of password hashes - there should be a unique salt for each user, but it's fine to store the salt in the same place as the hashed password.
Salts are best when they are dynamic (say the member's join date). Even if the attacker knows the way you compute the hash, they have to brute force each salted and hashed password -- which takes a lot of time, for (in general) little reward.
That being said, if the attacker is looking at your code server-side, you already have a much larger problem.
1) Don't use the same salt for multiple accounts. If you can't show your source-code and trust that your passwords are still secure, you've done it wrong.
2) PKCS #5 v2.1, section 4
Hopefully, your "source code" is running on a web server, and not on the client side (javascript) where anybody can see it.

Categories