PHP Hashed Master Passwords in Code - php

I'm developing a PHP web application that uses an LDAP server for authentication. However, in case the LDAP server goes down, or something else goes wrong and I still need to access the system, I want to have a master password written directly in the code.
The previous iteration of this system (which I did not write) simply stored the passwords as plaintext (!). So:
if ($username == "dan" && $password == "32fsss") {
which of course is extremely unsecure.
So I want to fix that. I was thinking of hashing the password, so doing
$hashedPassword = password_hash($password);
if ($username == "dan" && $hashedPassword == "HASHPASSWORDSTOREDHERE") {
So I would hard-code the hash for the master password, not the actual password itself. Is this secure? I know a stolen hash is bad, but it's better than a stolen plaintext password.
Of course all user-input would be appropriately sanitized.
Alternatively: any other thoughts for having a master-password access system?

If it's purely a read only incident and all they get is the hashed version, it shouldn't be an issue. That being said, I prefer to use the hash() function rather than password_hash(), but that's just my personal preference.
The only issue is if the attacker who reads the php file and obtains the hashed password has a way to reverse it (i.e. a rainbow table). In this instance, your system becomes insecure. This is where my preference for hash() over password_hash() comes from. With hash(). To generate the hashed form, I can say:
$HashedMasterPassword = hash('md5', $MasterPassword . "MyMD5Salt") . hash('sha256', $MasterPassword . "MyShaSalt");
Then in my uploaded code I can take the output of the above code ($HashedMasterPassword) and hard code that string into my code. This adds two different salts, two different hashing functions and it reduces the already low chance of a rainbow table attack because the attacker would need a collision that occurs for both md5 + the first salt and sha256 + the second salt. This is, I dare say the word, impossible. Sure, pigeon hole effect says it's possible and it is, but this is SO near impossible that I wouldn't fret over it.
That all said, using password_hash() and storing that hash is fine if you really want to. I just personally dislike it.
EDIT: ADDING ON IMPLEMENTATION DETAILS
I believe based on the comments that there was some confusion as to how this would be implemented. Let's say my master password was thisIsMyPassword (Super secret and super secure, I know). Well, we'd need to generate the hard coded hashed form. The hard coded hashed form would be found by saying:
$MasterPassword = "thisIsMyPassword";
$HashedMasterPassword = hash('md5', $MasterPassword . "MyMD5Salt") . hash('sha256', $MasterPassword . "MyShaSalt");
echo $HashedMasterPassword;
Important: You would NOT upload this to the server. This would just be used for generating the hash and it should then be permanently deleted.
The output of this would be: 6dcfc45fba2fff44b7cfc8df7245a1b7804c88d63a82ac2ba33e0de32ab7f20c5afe2c1784e87f1bae8a4f91f1a84833
So, in your code that requires a master password to override, you'd enter:
$MasterHash = '6dcfc45fba2fff44b7cfc8df7245a1b7804c88d63a82ac2ba33e0de32ab7f20c5afe2c1784e87f1bae8a4f91f1a84833';
$SubmittedMasterPass = $_POST['MasterPassword'];
$HashedVersionOfSubmittedMasterPass = hash('md5', $SubmittedMasterPass . "MyMD5Salt") . hash('sha256', $SubmittedMasterPass . "MyShaSalt");
if($MasterHash !== $HashedVersionOfSubmittedMasterPass){
die('Override Failed. Reason: Wrong Password.');
}else{
// User has successfully logged in using the master password.
}
Again to clarify based on information from the comments, this is more secure than just using SHA256 because a brute-forced master password must be found that produces 6dcfc45fba2fff44b7cfc8df7245a1b7 when MyMD5Salt is appended to the end of it and it also must produce 804c88d63a82ac2ba33e0de32ab7f20c5afe2c1784e87f1bae8a4f91f1a84833 when MyShaSalt is appended onto the end of it. This means the collision must satisfy two different algorithms which is much more difficult to do than satisfying just the Sha256 algorithm on it's own.
However, as noted in the comments, this does take a few more milliseconds to process; so, if decreasing execution time is a big priority to you, then it might be recommended to only use Sha256 on its own rather than using MD5 and Sha256 combined.

If the user has access to the source code. They can just change it, so it doesn't really matter.

One can discuss if such a "backdoor" is desirable or not, but if you cannot decide it for yourself, there are two ways to protect such a hardcoded password. Storing only the hash is surely much better than the plaintext password, because everybody with read-access to the code could otherwise use it on a running system.
The first possibilty is to use a slow hash algorithm with a cost factor, such as password_hash() which you proposed in your example. If an attacker has read-access to the code, he would have to brute-force this password, to use it on a live system. A slow hash algorithm will thwart brute-forcing, while MD5 and other functions are ways too fast (8 Giga MD5 per second). The drawback is a slowdown in your application when the password is verified.
The second possiblity is a very strong password. Choose a long enough random combination, e.g. 70 characters generated with a password-manager and use it as the master key. Even fast algorithms like SHA256 are out of scope for brute-forcing then, and your key is immune against dictionary attacks and does not even need salting.

Related

Converting php password hash to original value is that possible?

I am using code
$password1 = password_hash($password, PASSWORD_BCRYPT);
and trying to insert $encrypt to database.
I want to find out a way to decrypt them. Is that possible?? How?? Sorry if I am wrong.
No, and you're not supposed to be able to do it at all.
Hashing is, by design, supposed to be irreversible. That is the design goal. If you can reverse a hashing result of an algorithm, the algorithm is faulty and should be avoided.
Brute Force Cracking
There is a way to guess the password by brute force.
You can:
make a list of all the possible password combinations you can imagine. Then,
you can make a hash, with the same algorithm you used, of each and
every one of them.
If one of them matches the hash of your password,
there you have it.
Someone has already made tools for this purpose, you may try them. For example:
https://github.com/BREAKTEAM/Debcrypt
Don't be too hopeful. If the password you're cracking is not in the list of "all the possible password combinations you can imagine", then you won't be able to get it this way.
How hashed password are usually used
You'd usually compare the hash of the login user's password input with your database password hash. The same string going through the same hashing process would always give you the same result.
For example,
$user = my_get_user($_POST['username']);
if ($user === null) {
// login failed
// ...
} else if (!password_verify($_POST['password'], $user->password)) {
// login failed
// ...
} else {
// login success
// ...
}
As an honest service provider, you're not supposed to know your user actual password. And hashing is a way to ensure you can check users' password without knowing them at all.
No, you can't revert back to the original values. If you are using any encryption algorithm. Otherwise, Hackers would blow up your sites in seconds. The sole purpose of using hashing algorithms is to save and encrypt data using a very large value. There are many algorithms which do encryption some of them are md1 and sha1. Many websites offer that they can retrieve original value but not in an instant. It requires a brute force to retrieve original passwords.
Depends on your website program system platform. For some sites, its a combination of your password and another variable sometimes called "salt" with a secret algorithm, and really depends on the platform used, it could vary. If you create your own program you could probably hash and dehash your own password just to test your code, then you can reverse the process but it is very easy to decrypt. Some other use a secret key combined with your hash, and there are other ways to achieve that, but never directly.
MD5 Hash Generator http://www.miraclesalad.com/webtools/md5.php
MD5 Hash Decryption https://www.md5online.org/md5-decrypt.html
I haven´t seen a smart platform program to use the simple hash / decrypt hash algorithm as a password validation procedure. But you could write your own code for testing purposes only.

Username, Password, Salting, Encrypting, Hash - How does it all work? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Secure hash and salt for PHP passwords
Iv'e read a lot of posts both in stackoverflow and other websites talking about web security. Such as salting encrypting etc. And I'm kinda not getting it so a simple explanation would be really helpful.
So here's what I know so far. A user logs in types his username and password. The input then goes through a process. Lets say the username and password is combined like for example:
$username = (USERS USERNAME INPUT);
$password = (USERS PASSWORD INPUT);
$userinput = $username . $password;
Then we add some salt.
$salt1 = "13$13aVc!kd";
$salt2 = "4kr$!vlmeoc";
$salted = $salt1 . $userinput . $salt2;
Then we encrypt it.
$encrypted = encrypt($salted);
Then check with the database and if its right user gets logged in.
That's how it works right? But Iv'e read about brute force attack. It guesses the input values right? With the procedure above. Doesn't it shows that the attacker only needs to get the $userinput information correct to get in? He doesn't need to guess the long $encrypted string correct?
Note: Lets say in this situation there's no captcha, no number of tries limit, no lockout, nothing else but the one above.
Note: Be gentle I'm still learning.
If you rule out captchas, try limits, lockouts, et cetera... then yes. You just have to brute force the plain text string.
However, that does take time - at the very least, it's bounded by the rate at which the server will respond to login requests. Even if the developer doesn't add any measures to prevent brute forcing, the server itself can only go through the encryption + verification process so quickly, and can only handle so many parallel requests.
That said, this is why it's important to
As a user, use a strong, hard to brute-force password
As a developer, have adequate measures to prevent brute-forcing of your login process
Hashing and salting passwords isn't to protect against people who brute force the natural login process (there are other things that protect against that). Instead, they're to protect against potential compromise of the password storage itself (e.g. someone dumping the contents of the database).
Both hashing and salting serve to decrease the speed at which someone with access to the stored passwords can retrieve the plain text string they'd need to be able to go through the natural login process (of your site or other sites, given that passwords are commonly shared between sites) without tripping anti-brute-forcing security measures.
The idea of hashing and salting is more to prevent someone from taking user passwords if the database itself is compromised. If the passwords are stored as salted and hashed strings, the attacker can't just use them to access a user's account on another site.
Password encryption is one-way encryption (or rather its suppose to be in a secure site). That is to say you take the password and you make a hash form it. bcrypt for example is the acceptable standard for doing this today.
If its one-way encryption a lot of people wonder how it can check a password. But you just hash the password the user submits and compare it to what hash you stored in the database. This way if your database is stolen an attacker has to work a lot harder.
The problem with just hashing a password is easily brute forced or rainbow tabled. You can google rainbow table to learn more on that. But essentially its a way to turn these hashes back into passwords.
Enter salting. Salting is adding random data essentially to every password. This trumps rainbow tables. Meaning a compromised database will mean brute force. Which if you're using a hash system like bcrypt takes a lot of time and effort for the attacked.
Having said all that. Best not to reinvent the wheel. Just use a known good authorization system if you can.
See my answer here
And you should generate unique salts for each entry when you create the hash.
One problem with brute force attacks is when you use a fast encryption like SHA1 or MD5. These functions are build to run the password through an algorithm fast. Instead you could use the Blowfish method, which im no expert on, but long story short it takes more calculation for a returned value, than SHA1 or MD5. This means it may take 5 years to brute force a password, hashed with Blowfish because of calculation time.
The next example is made with SHA1 and MD5, so it's vulnerable to bruteforce attacks, however the salt part should be OK to use:
$salt = md5(microtime().uniqueid());
This will output a unique 32 charecter salt, which you will put together with the password.
$passwod = $_POST['password'];
$hashed_password = sha1($password.$salt);
Now you have to store both the password and the salt in the database. And when you check the user inputtet password you get the salt, and hash the whole thing.
$temp_pass = $_POST['temp_pass'];
$salt = //from database;
$database_pass = //hashed pass from database;
$hashed_temp_pass = sha1($temp_pass.$salt);
if(hashed_temp_pass == $database_pass){
//Welcome user!
}
else{
//go away
}

Is this a safe way to store my passwords?

I've been reading around a few different guides/tutorials on this topic and found the following:
Storing Passwords Securely using Salt in PHP
Secure Hash and Salt for PHP Passwords (Top Answer)
I know that what I've read there is a very secure way to store a users password. I've made an attempt to combined the 2 slightly while instead of using mt_rand like in the first example, I've generated my own dynamic salt.
Here is my code:
<?php
$static_salt = ""; // Removed value for obvious reasons
$dynamic_salt_choice = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$dynamic_salt_length = 40;
$dynamic_salt = "";
$dynamic_salt_max = strlen($dynamic_salt_choice)-1;
for ($i = 0; $i < $dynamic_salt_length; $i++) {
$dynamic_salt .= substr($dynamic_salt_choice, rand(0, $dynamic_salt_max), 1);
}
$password_length = length($password);
$split_at = $password_length / 2;
$password_array = str_split($password, $split_at);
$password = $password_array[0] . $static_salt . $password_array[1];
$password_hash = hash_hmac('sha512', $password, $dynamic_salt);
?>
According to me this is fetching a static salt, generating a dynamic salt, we're then splitting the given password in 2 parts in an array and adding the static salt in between the two password sections.
We are then hashing the password with sha12 along with the dynamic salt.
My question to you is, is this more secure or just as secure as the 2 methods I've linked to? Or am I making it more vulnerable by mixing things up this way?
I also take it storing $password_hash in a cookie along side a username cookie for automatic login is a big no-no? If so, how do websites remember you through cookies in a secure manner?
I'm trying to increase the level of security with my sites
well, to let you know, no password hashing ussue can increase your site security even a bit.
You have to focus on the other, much more important things such as SQL and file injections, XSS and CSRF vulnerabilities. If you keep your site secure, it will keep your passwords as well safe just as a side effect.
Next thing you have to focus on, is password strength. No hash can secure a a silly password like joe or 123.
As for the hashing itself - you can use whatever you wish, some basic things like using some sane salt like registration time or email and some number of iterations of whatever hashing function is enough. Don't put too much meaning in hashing. it is not the thing that requires SO much attention as inventing some extra-secure original algorithm.
My question to you is, is this more secure or just as secure as the 2 methods I've linked to? Or am I making it more vulnerable by mixing things up this way?
Dunno if you trust me (I bet you won't) but ALL these methods are secure enough and require no impreovement. And affect no security of the site but only passwords themselves in case they are stolen using another vulnerability in your site.
I also take it storing $password_hash in a cookie along side a username cookie for automatic login is a big no-no?
I don't think it's wise thing to reveal a hash itself. But again, it affects no site security but passwords potential vulnerability only. If your hash and password are strong enough, a logic is making me to say that it is safe enough.
Assuming that the $dynamic_salt is stored alongside the final $password_hash -- since the hash wouldn't be testable without it -- this scheme is quite weak. Using a salt does protect against rainbow tables, but a non-iterated HMAC leaves this scheme weak to brute-force attacks. (The length of the salt does you no good, as it's a known constant in the hash input. Putting it in the middle of the original password doesn't really help either.)
Overall, this scheme is far weaker than bcrypt(), as it only (effectively) iterates the hash twice. You're really no better off than if you simply were storing the password using a simpler scheme such as:
$salt = uniqid();
$password_hash = hash_hmac('sha512', $password, $salt);
But you're still better off using someone else's (tried and tested) password encryption routine, rather than cooking your own.
With regard to using the password hash in a cookie -- this is to be avoided, as it allows an attacker with read-only access to the database (e.g, via a SQL injection attack or a stolen backup) to impersonate any user in your application without knowing or changing their password. It also means that, if a user's computer has been set to automatically log in, the password hash is stored on it. I'd avoid this.
A better scheme might be to set a randomly generated nonce in a cookie when a user chooses to log in automatically, then store a hash of that nonce in the database. This way, the server can check the correctness of a login key without ever having to "remember" it.
This seems like a reasonable salting scheme, although possibly overkill. It probably doesn't need to be 40 characters long - you're just trying to blow up the size of a rainbow table, not make an unguessable nonce - but making it long won't hurt.
As for autologin, you should store (in a cookie) a random token that corresponds to a database entry pointing to the user's account. When the user changes their password, erase all these entries for that user. When generating this token, rand() isn't good enough - you need a secure, unguessable random number. Unfortunately, PHP doesn't really have a built-in facility for secure random numbers - mt_rand() is about as close as it gets, but I personally would directly read random bytes from /dev/urandom on a Linux system and use that to generate my nonce.
Salts can be used,but it has got its own limitations. Another way is using bcrypt.More information can be found at http://www.openwall.com/phpass/
And i think This SO article is more than enough Secure hash and salt for PHP passwords

SHA Encryption - Are Salts Really Needed?

I'm using Jquery SHA512.js to sent encrypt and send a username and password to the server.
At the server I'm doing the following to create my DB stored HASH:
$dbhash = = hash('sha256',(hash('sha512',$user) . hash('sha256',$extremesalt)));
This all works fine.
My Question is what value is the Salt?
At the point the Salt is applied to the password, the password is already on the server and not in transit across the Internet. Also the Salt is stored next to the password hash.
Therefore it appears someone would need to get my table with hash's and if they did they could also get the salt and the rest of my code and do what they wanted with my site in general.
I can see its good to apply a salt and I will do so but as it only occurs on the server and not from the browser to the server I question its value. Am I missing something?
One other question - is it possible to apply a salt from the browser to the server. I assume not or at least if you did it would be visible if one checked the source (eg: in my cause visible in jquery). Thus of no real value.
thx
The point of the salt is to make it harder to see if 2 people's passwords are the same. One thing about SHA is that it's not easily reversible. Most attacks involve generating hashes for common passwords so for reasonably complicated passwords it becomes harder especially with salts (some people use usernames as salts, others use randomly generated numbers). Usually you want to do this on the server side code (I don't think it's safe to do on browser code). You should also never store the actual password on the server you only store the hash (and maybe the salt if you don't already know it)
Upon a second look I see that you're using 2 hashes one after the other 256 and then a 512. This is a bad idea, use one and stick with it. You waste time computing multiple hashes.
Mixing hashes like that is rather pointless. Taking an sha512 hash and running it through sha256 necessarily cuts the keyspace in half, so all you've done is waste cpu time and double the odds of a collision. The odds will still be vanishingly small/microscopic, but it's still something to consider.
The salt is there as a butt-covering mechanism. If for some reason your database were to leak (e.g. a dump file got "lost"), it would be trivial to generate an sha256/512 rainbow table of common passwords and see if there's any hits on your table. The hash is there to make it far more expensive to generate a rainbow table. e.g. "password" is easy to hash and check for. "password#^$##%#^Y###$##^%$^Y%%$" is far less likely to be rainbowed.
I don't know your app, but wouldn't you want to just send the username/pwd to the server using SSL and let the public key encryption of SSL take care of the encryption for you. The server can then generate an appropriate hash to either store the hashed password or to compare to a previously stored hash for verification.
$dbhash = = hash('sha256',(hash('sha512',$user) . hash('sha256',$extremesalt)));
Should be (no need for double hashing)
$dbhash = = hash('sha512',$pass + $salt);
Where pass is the password and salt is something unique about the user (userid for example). If you opt for random value you need to store it with the hash.

What is md5() for?

I was reading this tutorial for a simple PHP login system.
In the end it recommends that you should encrypt your password using md5().
Though I know this is a beginners' tutorial, and you shouldn't put bank statements behind this login system, this got me thinking about encryption.
So I went ahead and went to (one of the most useful questions this site has for newbies): What should a developer know before building a public web site?
There it says (under security) you should:
Encrypt Hash and salt passwords rather
than storing them plain-text.
It doesn't say much more about it, no references.
So I went ahead and tried it myself:
$pass = "Trufa";
$enc = md5($pass);
echo $enc; #will echo 06cb51ce0a9893ec1d2dce07ba5ba710
And this is what got me thinking, that although I know md5() might not the strongest way to encrypt, anything that always produces the same result can be reverse engineered.
So what is the sense of encrypting something with md5() or any other method?
If a hacker gets to a password encrypted with md5(), he would just use this page!.
So now the actual questions:
How does password encryption work?
I know I have not discovered a huge web vulnerability here! :) I just want to understand the logic behind password encryption.
I'm sure I'm understanding something wrong, and would appreciate if you could help me set my though and other's (I hope) straight.
How would you have to apply password encryption so that it is actually useful?
What about this idea?
As I said, I may/am getting the whole idea wrong, but, would this method add any security in security to a real environment?
$reenc = array(
"h38an",
"n28nu",
"fw08d"
);
$pass = "Trufa";
$enc = chunk_split(md5($pass),5,$reenc[mt_rand(0,count($reenc)-1)]);
echo $enc;
As you see, I randomly added arbitrary strings ($reenc = array()) to my md5() password "making it unique". This of course is just a silly example.
I may be wrong but unless you "seed the encryption yourself" it will always be easily reversible.
The above would be my idea of "password protecting" and encrypted password, If a hacker gets to it he wont be able to decrypt it unless he gets access to the raw .php
I know this might not even make sense, but I can't figure out why this is a bad idea!
I hope I've made myself clear enough, but this is a very long question so, please ask for any clarification needed!
Thanks in advance!!
You should have an encryption like md5 or sha512. You should also have two different salts, a static salt (written by you) and then also a unique salt for that specific password.
Some sample code (e.g. registration.php):
$unique_salt = hash('md5', microtime());
$password = hash('md5', $_POST['password'].'raNdoMStAticSaltHere'.$unique_salt);
Now you have a static salt, which is valid for all your passwords, that is stored in the .php file. Then, at registration execution, you generate a unique hash for that specific password.
This all ends up with: two passwords that are spelled exactly the same, will have two different hashes. The unique hash is stored in the database along with the current id. If someone grab the database, they will have every single unique salt for every specific password. But what they don't have is your static salt, which make things a lot harder for every "hacker" out there.
This is how you check the validity of your password on login.php for example:
$user = //random username;
$querysalt = mysql_query("SELECT salt FROM password WHERE username='$user'");
while($salt = mysql_fetch_array($querysalt)) {
$password = hash('md5',
$_POST['userpassword'].'raNdoMStAticSaltHere'.$salt[salt]);
}
This is what I've used in the past. It's very powerful and secure. Myself prefer the sha512 encryption. It's actually just to put that inside the hash function instead of md5 in my example.
If you wanna be even more secure, you can store the unique salt in a completely different database.
Firstly, "hashing" (using a cryptographic one way function) is not "encrypting". In encryption, you can reverse the process (decryption). In hashing, there is (theoretically) no feasible way of reversing the process.
A hash is some function f such that v cannot be determined from f(v) easily.
The point of using hashing for authentication is that you (or someone seeing the hash value) do not have any feasible way (again, theoretically) of knowing the password. However, you can still verify that the user knows his password. (Basically, the user proves that he knows v such that f(v) is the stored hash).
The weakness of simply hashing (aside from weak hash functions) is that people can compile tables of passwords and their corresponding hash and use them to (effectively) get the inverse of the hash function. Salting prevents this because then a part of the input value to the hash is controlled and so tables have to be compiled for that particular salt.
So practically, you store a salt and a hash value, and authenticate by hashing a combination of the salt and the password and comparing that with your hash value.
MD5 is a one way hashing function which will guard your original password more or less safely.
So, let's say your password is "Trufa", and its hashed version is 06cb51ce0a9893ec1d2dce07ba5ba710.
For example, when you sign in to a new webpage, they ask you for your username and password. When you write "Trufa" as your password, the value 06cb51ce0a9893ec1d2dce07ba5ba710 is stored in the database because it is hashed.
The next time you log in, and you write "Trufa", the hashed value will be compared to the one in the database. If they are the same, you are authenticated! Providing you entered the right username, of course.
If your password wasn't stored in its hashed form in database, some malicious person might run a query somehow on that database and see all real passwords. And that would be compromising.
Also, since MD5 is a 128 bit cryptographic function, there are 2^128-1 = 340282366920938463463374607431768211455 possible combinations.
Since there are more possible strings than this, it is possible that 2 strings will generate the same hash value. This is called a collision. And it makes sure that a hashed password cannot be uniquely reverse engineered.
The only vulnerability with salting is that you need to know what the salt is in order to reconstruct the hash for testing the password. This is gotten around by storing the entry in the authdb in the form <algorithm>$<salt>$<hash>. This way the authdb entry can be used by any code that has access to it.
You're missing the important step - the salt. This is a unique (per user, ideally) bit of extra data that you add to the password before hashing it.
http://en.wikipedia.org/wiki/Salt_%28cryptography%29
Your idea (salting) is well known and is actually well-implemented in the PHP language. If you use the crypt() function it allows you to specify a string to hash, a method to encrypt (in some cases), and a salt. For example,
$x = crypt('insecure_password', $salt);
Returns a hashed and salted password ready for storage. Passwords get cracked the same way that we check if they're right: we check the hash of what the user inputs against the hash of their password in the database. If they match, they're authenticated (AFAIK this is the most common way to do this, if not the only). Insecure passwords (like password) that use dictionary words can be cracked by comparing their hash to hashes of common passwords. Secure passwords cannot be cracked this way, but can still be cracked. Adding a salt to the password makes it much more difficult to crack: since the hacker most likely doesn't know what the salt is, his dictionary attack won't work.
For a decent hash the attacker won't be reversing the hash, they'll be using a rainbow table, which is essentially a brute-force method made useful if everyone uses the same hash function.
The idea of a rainbow table is that since hashing is fast I can hash every possible value you could use as a password, store the result, and have a map of which hash connects to which password. If everyone just takes their passwords and hashes them with MD5 then my hash table is good for any set of password hashes I can get my hands on!
This is where salting comes in. If I take the password the user enters and add some data which is different for every user, then that list of pre-determined hashes is useless since the hash is of both the password and some random data. The data for the salt could be stored right beside the password and even if I get both it doesn't help me get the password back since I still have to essentially brute force the hash separately for every single user - I can't form a single rainbow table to attack all the hashes at once.
Of course, ideally an attacker won't get the list of hashed passwords in the first place, but some employees will have access so it's not possible to secure the password database entirely.
In addition to providing salt (or seed), the md5 is a complex hashing algorithm which uses mathematical rules to produce a result that is specifically not reversable because of the mathematical changes and dataloss in throughput.
http://en.wikipedia.org/wiki/Cryptographic_hash_function
md5 (or better put: hash algorithms in general) are used to safely store passwords in database. The most important thing to know about hashes is: Hashes are not encryptions per se. (they are one-way-encryptions at most). If you encrypt something, you can get the data back with the key you used. A hash generates a fixed-length value from an arbitrary input (like a string), which can be used to see if the same input was used.
Hashes are used to store sensitive, repeatly entered data in a storage device. Doing this, nobody can recreate the original input from the hash data, but you can hash an incoming password and compare it to the value in the database, and see if both are the same, if so, the password was correct.
You already pointed out, that there possibilites to break the algorithm, either by using a database of value/hash pairs or producing collisions (different values resulting in the hash value). You can obscure this a bit by using a salt, thus modifying the algorithm. But if the salt is known, it can be used to break the algorithm again.
I like this question. But I think you've really answered yourself.
The site you referenced uses dictionary lookups of known, unsalted, md5's - it doesn't "crack" anything.
Your example is almost good, except your application needs to be able to regenerate the md5 using the same salt every time.
Your example appears to use one of the random salts, which will fail 2 of 3 times if you try to compare a users password hash to something input.
People will tell you to also use SHA1 or SHA256 to be have a 'stronger' hash - but people will also argue that they're all 'broken.'
That documentation is misleading -- it teaches a "vulnerable" concept and presents it as somehow being "secure" because it (the saved password) looks like gibberish. Just internet junk that won't die. The following link should clear things up (you have already found a good bit of it though, it seems. Good work.)
Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes talks about MD5 (and why it should not be used) along with salt (e.g. how to thwart rainbow attacks) as well as provides useful insights (such as "Use someone else’s password system. Don’t build your own"). It is a fairly good overview.
This is my question about the aspects of md5 collision, slightly related to your question:
Is there any difference between md5 and sha1 in this situation?
The important part is in the first 3 rows, that is: you must put your salt before the password, if you want to achieve stronger protection, not after.
To simply answer the title of your question, md5's only real use nowadays is for hashing large strings (such as files) to produce checksums. These are typically used to see if both strings are identical (in terms of files, checksums are frequently used for security purposes to ensure a file being distributed hasn't been tampered with, for example).
To address each of your inline questions:
How does password encryption work?
How would you have to apply password encryption so that it is actually useful?
Secure password hashing works by taking the password in plain text form, and then applying a costly hashing function to it, salted with a cryptographically secure random salt to it. See the Secure hash and salt for PHP passwords question for more detail on this.
What about this idea?
Password hashing does not need to be complicated like that, and nor should it be. Avoid thinking up your own algorithms and stick with the tried and tested hashing algorithms already out there. As the question linked above mentions, md5() for password hashing has been obsolete for many years now, and so it should be avoided.
Your method of generating a "random" salt from an array of three different salts is not the randomness you're looking for. You need unique randomness that is suitable for cryptographically secure (i.e. using a cryptically secure pseudo-random number generator (CSPRNG)). If you're using PHP 7 and above, then the random_bytes function can be used to generate a cryptographically secure salt (for PHP 5 users, the random_compat library can be used).

Categories