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!
The password hash stored by MySQL Server is generated by hashing the plain-text password twice using SHA1. When the client transmits the password to the server, it uses three pieces of information: The SHA1 hash of the plain text password. The SHA1 hash of the the SHA1 hash of the plain text password.
To protect passwords, experts suggest using a strong and slow hashing algorithm like Argon2 or Bcrypt, combined with salt (or even better, with salt and pepper). (Basically, avoid faster algorithms for this usage.) To verify file signatures and certificates, SHA-256 is among your best hashing algorithm choices.
The client can do this by using the PASSWORD() function to generate a password hash, or by using a password-generating statement ( CREATE USER , GRANT , or SET PASSWORD ).
The MySQL MD5 function is used to return an MD5 128-bit checksum representation of a string. The MD5 message-digest algorithm is a widely used hash function producing a 128-bit hash value. The value returned by the MD5 function is a binary string of 32 hexadecimal digits, or NULL if the argument was NULL.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With