Is storing a salt in the MySQL table secure? [duplicate] - php

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best way to prevent SQL Injection in PHP
The necessity of hiding the salt for a hash
I'm very new to MySQL and PHP, and have started self-learning it over the past couple of days and today I was looking at encryption for passwords etc. I've been looking through many webpages with information on the topic and most of them are saying to generate a random salt for every entry in the table (which I understand, you don't want the same salt for every entry) and this salt should then be stored in the table alongside the entry.
From what I've understood (correct me if I'm wrong), the encryption of the password doesn't prevent hackers from accessing it, rather just masks the true value if they do get access to the database. Surely if this is the case, you wouldn't want to store the salt in the table too - if the hacker has accessed the database and can see the encrypted data, showing him the salt just makes his job of decrypting infinitely easier?

The salt isn't used to encrypt. Instead, it goes (together with the password) into a hash function. That way, nobody (not even your application) can determine the password, but you can verify a password.
The salt is then used to require the attacker to attack each password hash individually (if the attacker wants just one password, the salt doesn't help in any way). Thanks to rainbow tables, it is fairly easy to compute the outputs of the hash function for common passwords.
The salt value is not secret, and can be safely stored in a MySQL database (or even published).

The purpose of the salt is to prevent the use of Rainbow tables.These would allow a hacker to have generated a large number of pre generated hashes for certain passwords. By appending the salt to the password before it is hashed the hash is completely different than the original password.
password => 5f4dcc3b5aa765d61d8327deb882cf99
password+saltvalue => 1d7dc54c316b11f3a38cc24fa68e2b6a
thus they would need to recreate the hash for each salt value which is unpractical.

It is perfectly fine to store the salt in the way that you are planning to. In fact it is fine to allow the attacker to see the salts. The purpose of the salt is to prevent people from being able to use prebuilt look up tables called rainbow tables by extending the size of the message space. All the salt does is make them throw out any precomputation and solve the whole problem which is time consuming but certainly possible (especially for hashes like md5 -- you should move to sha256)
You want to use different salts for each user so that an attacker would have to do the full amount of work for each password they recover rather than just generate a new table based on a single salt.

You can consider salt as something 'semi unique', it really does not have to be additional column called salt. Username, user email is also a kind of salt. So they are actually stored in db, next to hashed password. One problem with this approach occur when user decide to change a username or email.

Related

I have accidentally used md5 to hash passwords, is it possible to create script to change everyone password? [duplicate]

This question already has answers here:
Is it possible to decrypt MD5 hashes?
(24 answers)
Closed 5 years ago.
Before knowing about just how dangerous md5 is, I have used it to store passwords. Md5 is terrible for security, and can easily be decoded. I now have 70,000 users registered in my database. Big mistake.
Now, since MD5 can be decoded into a string easily I was wondering if it is possible to loop through everyone's password in my MySQL database, decode it, and change it to a much stronger salt hashing system where it cannot be decoded to a string again. Would this be a viable option or even possible? Or is my only solution to do a hard database reset. Prompting users to change passwords would not be a good solution.
No. However, you can work around it, sort of:
Add a new field to your database to hold a second password.
Allow your users to log in as normal, with the MD5 system.
After they have successfully authenticated, you know their password. So now just use password_hash() on it and store it in the new field.
After some amount of time has passed, all active users will have their password encoded both ways.
Remove the MD5 authentication and replace it with password_verify().
Any users that hadn't logged in during the transition period will simply have to reset their password.
Keep the transition period as short as reasonably possible. This will allow your most active users to transition transparently without having to leave your system exposed for too long.
Note -- ultimately, you should have them change their passwords, as the current ones should be considered weak.
Edit for clarification:
You don't necessarily need to make a new password column. Since the hashes generated by password_hash() can be easily differentiated from those generated by md5(), you can simply use a strlen() check to determine which method to use. However, if you made your password field exactly the width of an MD5 hash string, then it's not going to be wide enough to hold the output of password_hash().

Is it an good idea of Using password itself as an salt

I have read in many articles that we should combine an unique salt to each passwords before hashing and store the salt in database for verification but How about using the password itself as an salt ?
Doing this will benefit as the salt will be unique for each as well as it will be hidden as it will be stored no where.
An simple example I can give for above is:
$hashToStore=sha1(strrev($password).$password);
Above I am just reversing the password and using it as an salt (I will be doing something more complex then just reversing it in development.)
Is This an better way for storing passwords or will be a bad practice.
PS:I am completely aware of php latest inbuilt functions such as crypt() and use it in real world, but yet wanted an review for above.
A common mistake is to use the same salt in each hash. Either the salt is hard-coded into the program, or is generated randomly once. This is ineffective because if two users have the same password, they'll still have the same hash. An attacker can still use a reverse lookup table attack to run a dictionary attack on every hash at the same time. They just have to apply the salt to each password guess before they hash it. If the salt is hard-coded into a popular product, lookup tables and rainbow tables can be built for that salt, to make it easier to crack hashes generated by the product.
A new random salt must be generated each time a user creates an account or changes their password.
[…] It's easy to get carried away and try to combine different hash functions, hoping that the result will be more secure. In practice, though, there is very little benefit to doing it. All it does is create interoperability problems, and can sometimes even make the hashes less secure. Never try to invent your own crypto, always use a standard that has been designed by experts. Some will argue that using multiple hash functions makes the process of computing the hash slower, so cracking is slower, but there's a better way to make the cracking process slower as we'll see later.
Here are some examples of poor wacky hash functions I've seen suggested in forums on the internet.
md5(sha1(password))
md5(md5(salt) + md5(password))
sha1(sha1(password))
sha1(str_rot13(password + salt))
md5(sha1(md5(md5(password) + sha1(password)) + md5(password)))
Do not use any of these.
Salt should be generated using a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG). CSPRNGs are very different than ordinary pseudo-random number generators, like the "C" language's rand() function. As the name suggests, CSPRNGs are designed to be cryptographically secure, meaning they provide a high level of randomness and are completely unpredictable. We don't want our salts to be predictable, so we must use a CSPRNG. The following table lists some CSPRNGs that exist for some popular programming platforms. (PHP: mcrypt_create_iv, openssl_random_pseudo_bytes)
The salt needs to be unique per-user per-password. Every time a user creates an account or changes their password, the password should be hashed using a new random salt. Never reuse a salt. The salt also needs to be long, so that there are many possible salts. As a rule of thumb, make your salt is at least as long as the hash function's output. The salt should be stored in the user account table alongside the hash.
To Store a Password
Generate a long random salt using a CSPRNG.
Prepend the salt to the password and hash it with a standard cryptographic hash function such as SHA256.
Save both the salt and the hash in the user's database record.
To Validate a Password
Retrieve the user's salt and hash from the database.
Prepend the salt to the given password and hash it using the same hash function.
Compare the hash of the given password with the hash from the database. If they match, the password is correct. Otherwise, the password is incorrect.
At the bottom of this page, there are implementations of salted password hashing in PHP, C#, Java, and Ruby.
In a Web Application, always hash on the server
If you are writing a web application, you might wonder where to hash. Should the password be hashed in the user's browser with JavaScript, or should it be sent to the server "in the clear" and hashed there?
Even if you are hashing the user's passwords in JavaScript, you still have to hash the hashes on the server. Consider a website that hashes users' passwords in the user's browser without hashing the hashes on the server. To authenticate a user, this website will accept a hash from the browser and check if that hash exactly matches the one in the database. This seems more secure than just hashing on the server, since the users' passwords are never sent to the server, but it's not.
The problem is that the client-side hash logically becomes the user's password. All the user needs to do to authenticate is tell the server the hash of their password. If a bad guy got a user's hash they could use it to authenticate to the server, without knowing the user's password! So, if the bad guy somehow steals the database of hashes from this hypothetical website, they'll have immediate access to everyone's accounts without having to guess any passwords.
This isn't to say that you shouldn't hash in the browser, but if you do, you absolutely have to hash on the server too. Hashing in the browser is certainly a good idea, but consider the following points for your implementation:
Client-side password hashing is not a substitute for HTTPS (SSL/TLS). If the connection between the browser and the server is insecure, a man-in-the-middle can modify the JavaScript code as it is downloaded to remove the hashing functionality and get the user's password.
Some web browsers don't support JavaScript, and some users disable JavaScript in their browser. So for maximum compatibility, your app should detect whether or not the browser supports JavaScript and emulate the client-side hash on the server if it doesn't.
You need to salt the client-side hashes too. The obvious solution is to make the client-side script ask the server for the user's salt. Don't do that, because it lets the bad guys check if a username is valid without knowing the password. Since you're hashing and salting (with a good salt) on the server too, it's OK to use the username (or email) concatenated with a site-specific string (e.g. domain name) as the client-side salt.
source: https://crackstation.net/hashing-security.htm
So, to answer your question, bad idea, very bad idea.
Please, don't ever do this. The whole point of salting is that every persons password hash will be unique which removed the issues of rainbow tables and giving away who has the same password.
Why does that matter? Look at the LinkedIn hack where they had "password hints". People has hints like "rhymes with assword" which gave away what their password, and also their hash was. It also gave away EVERYONE ELSE who was using the same password.

How to get salt from a password and use it to validate user? [duplicate]

This question already has answers here:
Secure hash and salt for PHP passwords
(14 answers)
Closed 8 years ago.
I have read tons of questions and tutorials about encrypting a password, and while I've learned a lot, nowhere did I find an answer to this.
I want to use crypt() for hashing a password that I will store on Database. I also know I need to use a salt so it works properly, and I've read that the best way to generate a random salt is by using this or something similar.
If I understood correctly the process is this:
User enters a password
Random create a salt
Hash password and salt
Store result in database
But then how do I recover the salt when user tries to login?
User enters his password
I somehow add his own unique randomly generated salt
Hash both of them together
Compare it to hashed salted password stored in Database.
In a few questions I've found, one of the answers was to store the randomly generated salt on the database. But I thought the whole purpose of salting was to be more secure, if an attacker got access to my DB he would see the 'salt' fields and even if my passwords are encrypted he would gain easy access to accounts.
Other answers said that the 'salt' is prepended to the password when using crypt() so there is no need to store it in a separate field. My question is, how do I get access to it? Is there some function that does this and I'm totally missing?
You store the salt in your db, along with the hashed password, i.e. hash(salt+password).
If your database gets compromised and someone gets all the hashes and the salts, they cannot run a rainbow table attack against your hashes - they will need to brute force each hash. With a good hashing algorithm, the brute force attack is unfeasible.
What is a rainbow table attack?
Lets assume a generic hashing algorithm, hash(f).
I, as an attacker, precalculate common passwords (f) and their hashes (hash(f)). Now, when I get your unsalted database of hashes, I just need to look through your database for hashes that match my precalculated table (rainbow table).
For example, if my rainbow table stores that for f = qwerty, hash(f) = someRandomHash, I look through your database for someRandomHash and as soon as I find it, I know that user's password is qwerty.
However, if you salted your passwords, when a user set his password as qwerty, you calculated his hash as hash('saltqwerty), which means, you did not calculate his hash as someRandomHash but instead as someRandomSaltedHash. This renders my rainbow table completely useless.
I am left with no choice but to brute force your table. I know the salt, but I don't know the password, so I have to calculate hash(salt+password) for every possible permutation and combination of password. With a slow enough hashing algorithm, this can take centuries (worst case).
How do you login a user?
User submit his user_id and password. You query the database for the salt for that user. Then you compute hash(salt+password) and compare against the hash stored in your database.
You can safely store a hashed password and a salt in the same database - the idea is that since the salt is different every time, even the exact same passwords will be stored differently in the database, which virtually eliminates brute-force lookup weaknesses associated with things like md5-encoded passwords.
Out of an obvious mass confusion, if you're able to use PHP v5.5.0 or higher, password storage has become remarkably easier with the use of password_hash and password_verify.
As an additional benefit, these functions don't require you to have separate password and salt fields in your database - you can simply store the returned password_hash value and use password_verify with the clear-text password to validate.
I don't know a lot about high level security DB, but how about this?:
hashedPassword = hash(UsurID+GivenPassword)
So, at logon time, youget first the User Login, and his ID, and then the given password to compare with the hashedPassword tha is already in DB.
As I said, I dont know if this will increase security, but at least it makes all passwords differents, doesn't?
Anyway, I'm still learning too.

PHP SECURITY dynamic generated user hash password on every login or hash system changes

I'm knowing this site http://www.openwall.com/phpass/, but idea is on salt on mainly system.
Example, ZEND use system('uname -a') and it's hashed to md5() for using ROW LEVEL user SALT encryption. This is combination of user password, user login name/email address and server name as sha1/md5/...
But, my idea is generate DYNAMIC SALT instead STATIC SALT such as system('uname -a'). Example, every time when user is logged in, SALT has been changed but not user password.
For more security reasons, i'm needing dynamicaly changes salt on database or external file on daily basis or using third-party such as checking data from another server for salting?
What are best method for securing user sensible data on users database table and currents login. Cookie also is very bad secure options for me. It's must works such as PayPal API Tokenize and user id...
I'm using current:
salt from every user
salt from system hashed
hashed combination of user password, user salt and system salt
SHA-512 crypt() or bcrpyt() class
dynamically salt ? idea?
You are doing it wrong.
I think you are missing a key fact about re-hashing the password. To do it, you would have to store it in a recoverable form. Thus, creating even greater security risk, if system is compromised.
Here is what i would do:
make passwords expire in 60 days (or, you can choose some other number, just not too often).
each time user sets new password, you generate a random salt
build hash with crypt(), using CRYPT_SHA512 or CRYPT_BLOWFISH hashing algorithms
set a bit higher amount of rounds .. 20'000 should be enough
store the whole result that crypt() returns in the hash field in db.
Also you might benefit for reading: Properly Salting Passwords, The Case Against Pepper.
Changing the salt doesn't improve anything.
The point is: you always need to store salt and hash together somewhere because when you compare the password input with the hash you need to hash the input - obvious, right?
So this is the point: even if you change the salt after every login and do some weird re-hashing of the password it changes nothing because as soon as an attacker gets the database he has both hash and salt (if it's stored there together, which is necessary if you always use a different salt for each user which is something you should do).
A far more better way is extending the hashing by using 1000-10000 rounds of hashing as well as a long salt (you can easy use 512 bytes for the salt). These are better tip's than doing some re-hashing.
But anyway: if you really want to improve your PHP application you should focus on avoiding security issues like SQL injection, XSS, CSRF, RFI, LFI, file disclosure, RCE, etc - if an attacker gets access to the server he can simply backdoor the login script to send him an e-mail containing the plaintext credentials every time someone tries to login. (Well, you can also avoid this if you use a challenge-response authentication implemented in javascript like CRAM-MD5 http://en.wikipedia.org/wiki/Challenge-response_authentication or using RSA (also implemented in JS) to securely send login data).
Salt is only used to prevent against precomputation attacks, such as Rainbow Tables. Thus if someone wants to bruteforce the hashes, they actually have to compute them one at a time at runtime. (and not merely do a lookup in a database of pre-computed hashed values)
It's not really clear what the problem is that you're trying to solve. You just say:
"For more security reasons, i'm needing dynamicaly changes salt"
If that problem is precomputation attacks, then just have a normal salt. If it is not a precomputation attack, then salt is almost surely the wrong solution.

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