# What's wrong with md5($_GET['password'])?

Storing your users' passwords securely is critical.

But still, you can find code like `$hash=md5($_GET['password'])` in many code bases.

So, what's wrong about it?

## Using `md5` to hash passwords

While it's good to see use of a hash in the code - instead of storing the password in plain text - **`md5` is not a good choice (anymore)** because  ["The security of the MD5 hash function is severely compromised"](https://en.wikipedia.org/wiki/MD5).

## No "salt"

What makes things worse is not using any kind of salt but just the password as input to the hash.

This makes the code **vulnerable to  [rainbow table attacks](https://en.wikipedia.org/wiki/Rainbow_table)**. "Rainbow tables" are pre-computed tables mapping a hash to its original input. So, if you know a hash of password, you can lookup the original string very quickly without any computation!

At least for common passwords without salt (or very simple salt).

So, to better protect the code against such an attack, at least this code would be better (still _not_ good!):

`$pw=md5($_GET['password'] . 'myHardToGuessHashSalt')`.

This way, one would need to have a rainbow table of all passwords, but with `myHardToGuessHashSalt` appended to each of them. It's way less likely someone ever pre-computed such a table and would have to compute such a rainbow table before starting attacking you.

To make attacks even harder, you can create a _random_ password for _each_ single password you store and save it along the hash. This way, an attacker would need to create a rainbow table for each single password, which essentially requires the same computation time as a brute-force attack anyway.

## Using `$_GET['password']`

This requires you to send the password from the browser to your server via a GET rather than a POST request. While this not really is a problem when using HTTPS, still GET parameters are much more **prone to end up in browser histories or server logs** - revealing the sent password in plain text.

# Solution: Use a proper hash algorithm with salt

Fortunately, all the aforementioned problems are already solved for you: just use [`password_hash`](https://www.php.net/manual/en/function.password-hash.php) function to hash your passwords.

It lets you choose a solid, proven hash algorithm like [`bcrypt`](https://en.wikipedia.org/wiki/Bcrypt) (or defaults to a good one) and automatically creates a random, strong salt for your hashed password.

So, this is how you properly hash a password in PHP:

1. When prompting the user for their **password while creating an account**, send the password via a `POST` request.
2. Use [`password_hash`](https://www.php.net/manual/en/function.password-hash.php) to properly **hash the password** and store the returned hash string in your **database**.
3. When the user tries to **log in** later, again, send the input password via a `POST` request.
4. Use [`password_verify'](https://www.php.net/manual/en/function.password-verify.php) to **check the password**. Just pass in the password the user entered and the user's password hash retrieved from your database.

%%[footer]

