is reversing an MD5 hash of password very effective? - php

basically,
$stored_hash = strrev(md5($plain_text));
Because, now rainbow tables and pre-computed attacks might get a hit on the hash, but when the attacker types in the calculated plain text, it will not authorize because the orginal hash is computed differently.
can i implement this on my app?

You should not use MD5 for hashing passwords; even though certain "tricks" may make it harder to reverse engineer passwords, rainbow tables for reversed passwords may already exist, and if they don't they can be generated.
See this article from PHP on the issue. Essentially it boils down to that you should use password hashing functions that are provided by PHP. Using these has the additional advantage that, when you run your application on a future version of PHP, it may use a more secure hashing algorithm than it does now.

Related

Hashing authentication data in 2013

I am facing the never ending problem How to store passwords in DB?. As far as I read recently there ware a few of the previously considered safe algorithms, which had been marked as insecure. So I am struggling to find a up-to-date resource which describes the ones that are not secure any more.
I was thinking of combining two or three algos, but I remember back in the day it was considered insecure, i.e exposes the hash to attacks. The combination I was thinking of was something like that:
data_h1 = sha256(sha1(data_salt).sha1([username|email]).sha1(data_peper))
data_h2 = sha256(sha1(data_salt).sha1(user_entered_password).sha1(data_pepper))
hmac(
sha512,
data,
sha512(general_salt.data_h1.data_h2.general_pepper)
);
Where data_salt and data_pepper are constants, hard-coded in to the application, but are different than general_salt and general_pepper which are as well hard-coded constants. [username|email] is the value supplied by the user on registration and when logging in, as well as *user_entered_password* (doh!).
Will this compromise security in some way? (if no go to next)
Will there be a major bottleneck due to the hash-o-mania which will be going on in the process of generation? (go to next)
Any recommendations on the approach showed above?
My questions goes for PHP, but will be good to see what will you guys recommend and what will your comments be in general, b`cuz I do think that this is very common task, and many people still use only MD5 or SHA1 (or better yet, storing in plain text).
The main reason not to use SHA-1 or SHA-256 alone for hashing passwords is that
they are fast, relatively speaking. Password authentication is vulnerable to dictionary
attacks and brute-force attacks, since users tend to include common words in their passwords
and use relatively short passwords, making them easier to guess than encryption keys.
Hash functions like bcrypt and PBKDF2 are recommended because they are slow.
They can be tuned to take almost any amount of time; it should take as long as
possible to hash a password without causing unreasonable delay. This will help slow
dictionary attacks and brute force attacks.
However, this is not the only security consideration for password storage.
When "storing" passwords you do not actually store the password, you store its one-way hash. The reason for this is to prevent even someone with access to the system from learning a user's password. The "one way" aspect of the hash means that, while it is possible to create a hash from the plaintext, it is impossible to learn the plaintext from the hash.
In addition, all passwords should be concatenated with salt (a random sequence of digits) before being hashed. The salt value should be stored along with the hash in the database. The salt must be ROW-SPECIFIC, i.e. every password should have its own salt.
Why must hashes be row-specific? Imagine a hacker has somehow obtained a copy of your database. Normally he's up against a pretty big brute force task. If you have only one hash, the hacker can examine all the rows and find rows that occur the most frequently, because the same password + the same salt always renders the same hash. So with this information he can guess that those rows contain commonly-used passwords. He can then use that information to reduce the size of his brute force problem. Or he can try to learn one of those users' passwords and then be able to use that password on any of the other users' accounts that have the same hash. The whole point of the salt is to prevent attacks of that nature.
Use a decent one-way cryptographically secure hash with a user-specific salt. That is the standard means of storing passwords.
The addition of application-specific "pepper" (which is the same every row, and must be cryptographically random and held in a secure location) tranforms the hash into an HMAC (Hash-Based Message Authentication Code), which is even better. If someone knows your hashing algorithm and salt but doesn't know the pepper, he will have a much harder time guessing the password.

Ultimate password salt

So recently I have been doing tons of research on how to secure passwords. I believe I understand the basics of it. As such I am attempting to write my own function to secure a password in php.
But I am somewhat confused when it comes to salting a password. We create a random unique salt and append it to a password and then hash it, and finally store the unhashed salt and hashed password/salt combination together in the database. This increases the search space of the hacker if he obtains access to the database and our hashed passwords.
So this seems like complete overkill of security, but everywhere I see the salt is always appended to the front or back of the password anyways. So looking at a SINGLE user's password this unique salt doesn't affect the search space does it? Although since each user has a unique salt the overall search space of EVERY user is dramatically increased.
Wouldn't it be more secure to create an algorithm that inserts the salt to a predictable, semi-random place in the password such as the length of the username/2? For example here is the steps of my proposed securing function:
Create a random salt
take username length %(mod) password length
insert the salt at the spot determined
hash
Example run:
random salt = 12345
len("imauserwithalongname") % len("mypass") = 2
valueToHash = my12345pass
Now our cracker has no idea where to put the salt without seeing our php/source, which (correct me if I am wrong) is much harder to gain access to than the database.
Also I know security should depend on the security of the key not secrecy of the algorithm, however I see nothing wrong with adding layers based on it, as long as the entire system does not depend on secrecy of the algorithm.
EDIT: Would doing this dramatically increase the search space of a cracker?
And what if we placed the salt in a place that depended on the length of the password, would that not destroy the purpose of using dictionary attacks, even on a per user basis?
Inserting the salt in a different spot doesn't increase the search space. If you are using a random salt for each user, a hacker does not know what each salt is per user anyway. The knowledge of its position in the unhashed string doesn't matter.
Use bcrypt or PBKDF2. Both algorithms enforce a salt and number of cycles. If you're patient enough, PHP 5.5 will just let you do password_hash($password).
As such I am attempting to write my own function to secure a password
in php.
Woah woah, hold it right there.
There's a saying passed down from cryptographers to us mere mortals which has held true for many many years. The saying goes like this:
Do not invent your own crypto.
Say it out loud, then say it again.
I know you're only trying to secure your passwords, but I had to get that out of the way. There are lots and lots of tried and tested methods to do what you want to achieve.
I appreciate you've done some research, but the internet is full of terrible terrible information, so I'm going to point you towards some useful articles.
Check out ircmaxell's security related
blogs.
A nice short list.
Here's some keywords to help you.
Bcrypt
Scrypt (someone please unstrike this when PHP supports it)
Again a very short list.
To address your specific concern. Salts are not needed to be kept private, as you say they are designed to stop attackers precomputing tables of valid password/hash combinations. However if you use a weak hashing algorithm they lose their value very quickly.
Security through obscurity is not as great as it seems. If a hacker gains access to your DB, the odds are quite high that they will also gain access to your filesystem. If they gain access to your source your custom method of storing passwords is a moot point.
In summary, custom algorithm + weak hash = insecure.
Instead you want to use tried and tested key derivation functions / key strengthening algorithms.
These are designed to make the computer work really hard to generate the hash, and makes it very difficult for an attacker to brute force a password.
Bcrypt stores the salt next to the password, and is proven to be very secure. Secure enough in fact that it is currently the recommended way to hash passwords by security experts.
In PHP 5.5 a simple password hashing API has been introduced based on Bcrypt, and for versions under 5.5 there is a password hashing compatibility library that does exactly the same thing.
That should be enough for you.
I personally think you're overdoing it. The most efficient way to salt a hash would be to have a dynamic, record-specif one AND a static one stored in a read-only file on the system. This is a very efficient yet secure way of salting hashes.
I think you misunderstood the purpose of the salt. The salt does not increase the search space for an attacker, after all it is stored plaintext with the hash-value. The purpose of a salt is, that an attacker cannot build one single rainbowtable, and then retrieve all stored passwords.
If you would append the same salt to every password, then the attacker cannot simply use an existing precalculated rainbow-table from the internet, he has to build a new rainbow-table for exactly this salt (existing rainbow-tables will contain passwords like "horse", but not passwords like horse8ze*w398dhek3+qmxno0). Unfortunately this single rainbow-table can then be used to get all passwords.
So we use a unique salt for every password. An attacker would have to build a separate rainbow-table for each password now, but why should he continue with building the table, when he already found a match (?), he cannot reuse the table later for other passwords. In other words, brute-force is faster than building a rainbow-table, so we made rainbow-tables useless.
So the salt should be unique for each password and if possible it should be unpredictable. Those criterias are difficult to fulfill with a deterministic computer, the best you can do is, to use the random source of the operating system to build the salts. Good hash algorithms for passwords like BCrypt and PBKDF2 repeat the hashing to become slow, and combine password and original salt in each iteration. It is not just a concatenation of password + salt.
Your idea about putting the salt somewhere secret does add a secret (where is the salt?), that will work as long as the attacker doesnt know your code. Getting the database (SQL-injection) is indeed easier than gaining access to the code, but the same goal can be achieved much easier with a pepper.
I tried to sum up this in a tutorial, maybe you want to have a look at it.

Should I store my salt along with my hashed password in the database?

I've been reading a bunch of stuff about security and I'm just now starting to try and play around with the code. I want to use MD5 encryption with a salt. I ran across this nifty PHP script with random salt:
substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',5)),0,10);
It randomly generates some characters as salt, but then I was thinking: How would I go about checking logins? Do I remove the salt, or should I store it in the database?
You shouldn't be using MD5 for password hashing. See How can I store my users' passwords safely?
To answer your original question, the salt is stored alongside the HASHED password in the database. The salt is not meant to be secret if the hashed password is discovered. Its purpose is to prevent attackers from using rainbow tables.
Store it in database. Otherwise you can't compare password provided by user with hashed one.
Some even regenerate hash (with new salt) upon each successful login of given user, although commenters below argue this is not the best idea (see comments)
Okay, so salts are used for both one-way hashes and encryption. They make it harder to reverse the encryption or the hash. I think it's easier to draw the point out with hashes, so I'll write from that point of view, but the principles apply to encryption in general.
Imagine that you're saving passwords. One of your users chooses the word "kiwi" as a password. Because storing passwords in plain-text is stupid, you don't want to do that. You want to hash the password.
But, those pesky hackers out there have compiled huge databases of hash look-up tables. (Check this one out!)
So, how do we foil the hackers? By salting the user's input! The salt is a random string (or set of bits, properly) that is cryptographically combined with the user's input to produce a more secure hash.
For example, if the string to be hashed is still "kiwi" and our salt is "5m3d", a simple salt mechanism might concatenate the two into: "kiwi5m3d". The hackers probably have "kiwi" in their database, but probably don't have "kiwi5m3d". A good salting system will probably perform a much more complicated function than this.
So now the hackers need a new look-up database for each possible salt. Using a random salt means that the hacker will have to do a full-on brute force attack, rather than recycling previous computations or using someone else's look-up table.
You could choose a different salt for everything, or the same salt for all the things on your site. A different salt of each entity necessitates a new brute force attack for each entity, but it can make implementation more difficult because each salt must be saved, rather than having one global salt (which, for data which is already somewhat random, e.g. passwords, should be sufficient).
In the case of encryption, look-up tables are still a possibility, but the data to be encrypted is generally varied enough that they're not feasible. So it becomes a game of playing "guess the password". It's easy to guess "kiwi" and hard to guess "kiwi5m3d".
You will have to save the salt somewhere, because it's the only way to "know" what's been hashed or encrypted. In the case of a hashed, you compare the user's original hash against the salted hash of their input. In the case of encryption, you need the salt to decrypt the data.
Where do you go from here?
First, don't use MD5. I gave you a link to an MD5 look-up database above. The function's increasingly considered to be weak. The sha class of algorithms is a better choice.
Second, make sure you choose a good salt. Longer and randomer is better. Computers are kind of bad at generating random data. This site could be one good choice and has a pretty good break-down of how it generates its random numbers.
Third, consider salt algorithms. Simple concatenation should work, but maybe HMAC (something I don't know much about) would be better.
You would have to store it in the database, otherwise you would not have anything to compare it to. The thing to remember with using a salt, is that the complexity can vary and without knowing what the salt is, the likelihood of it being brute forced hack is dramtically decreased.
Example:
$password = "banana";
$salt = "a12dsfg33B1cD2eF3G"; # Can be any assortment of characters
$password = md5($salt.$password);
Then you would just attach the same salt (would have to match to work) and pass the same function to your login script that combines the salt and the supplied password. You would then check that to the value in your database to authenticate the user.
Do not invent your own password-hashing scheme, however nifty it may look. Having a secure system is hard because you cannot really test for security. What you need is the following:
For each password instance, a random salt of sufficient length is created.
The random salt is stored along the hashed value; you will need it to verify the password afterward.
The password hashing process must be (configurably) slow, with many (many) nested invocation of whatever hash function is internally used.
Preferably, the internal hash function should use operations which are efficient on a PC but slow on a parallel architecture (a GPU).
Such a thing exists, it is called bcrypt and you can get it in PHP with the portable PHP password hashing framework.

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

What function to use to hash passwords in MySQL?

I have a user table in my mysql database that has a password column. Currently, I use the MD5 algorithm to hash the users' password for storage in the database. Now I like to think that I am a security conscience person. I noticed while reading the MySQL docs that they don't recommend MD5 or the SHA/SHA1 hashing methods, but don't offer an alternative.
What would be the best way to hash my passwords in MySQL? A function that is natively supported in both PHP and MySQL would be ideal and necessary with my current implementation.
Thanks!
It's not necessarily that you shouldn't use MD5, as much it's that you shouldn't use just MD5, as this leaves you vulnerable to rainbow-table attacks (a rainbow table is a table of precomputed hash values - if your password is even remotely common or simple, the attacker needs merely to look up the hash and he knows your plaintext password.)
At the very least you should add a salt to every password so that any existing rainbow table is useless, forcing the attacker to generate an entire new rainbow table just for your database of passwords.
Better still is to use a different salt for every password in your database, say the username it's associated with, so that an attacker can't even generate a rainbow table for your whole database and has to crack each entry separately.
MD5 is also a very fast algorithm. Speed is the enemy when it comes to cracking - the longer it takes to generate a hash, the longer it takes for each attempt a hacker makes. Something simple like hashing the plaintext 100 times with a new additional salt each time would be barely perceptible (if at all) to a user logging in to your site, but it would increase the time it takes to brute-force a password by the same 100 times.
Far, far more detail here: http://www.codinghorror.com/blog/archives/000953.html
MD5 is considered to be weak by today's standards. It would still take some work to crack a hash made with MD5, but it's several times easier than guessing the password by brute-force. Ideally, cracking a hash should not be easier than brute-force.
SHA1 is also considered easier to crack than guessing the password by brute-force.
I actually contributed a patch to MySQL to surface the SHA224, SHA256, SHA384, and SHA512 functions from OpenSSL. These are recommended by NIST for password hashing (actually SHA256 and higher).
My patch was finished by MySQL engineers, and is included in MySQL 6.0.5 and later, if I recall.
If you use an earlier version of MySQL (and who doesn't), then you can probably use an implementation of strong hashing functions in your host language. PHP has the hash() function for example. You can do the hashing in your application and save the resulting message string to the database.
Don't forget to do salting, too!
This question is 7 years old. In that time we have progressed in computing to where MD5 and SHA1 are now easily broken by modern computers. These should be avoided now.
With PHP 5.5 came the introduction of password_hash, which uses the far more secure bcrypt algorithm. While MySQL can encrypt/decrypt bcrypt, it's a terrible solution because you're not only adding a potentially large computation load to your database layer, but the unhashed password could be stored in your logs
Under no circumstances should a plain text password hit MySQL, even if at the query level. Otherwise you risk writing the passwords to log (query log, general log, slow query log, etc). Which is horrific. So no, don't even bother...
MD5 and SHA-1 probably aren't recommended anymore due to know attacks. But, they're still generally sufficient for most use cases.
If you're looking for more options, just use PHP's hash functions -- you've got plenty of options there.
I am using a combination. For example SHA1(MD5()) is working fine.

Categories