Just to add a little bit to what Glenn was saying: it might be worth explaining a little bit about how password storage/authentication works, because once you know that it should be clear why changing the salt every time is not going to work (and sorry, I should have picked up on that earlier!). You probably know some of this, but I'm guessing not all (as otherwise you wouldn't be regenerating the salt).
When a user enters a password on a website when they're signing up, you want
- When they log in, to be able to check the password that they entered for this login attempt against the one they originally entered, and
- To be reasonably sure that if somehow someone bad was to get hold of your database, they won't be able to work out what your users' passwords were.
So, in a simple implementation (too simple for today's world), you would hash the passwords -- that is, put them through a one-way cryptographic function, where you can easily calculate that hash("apassword")
is a number like "2132132343134", but it's incredibly computationally expensive to work out what passwords the number might be generated from.
When the user originally enters their password, you would calculate the hash
of the password and store that in the database. And when the user tries to log in again later, you calculate the hash
of the password they entered, and check if it matches the one you stored originally, and if they match then you know the password was right.
Nowadays, of course, doing things simply like that is not such a good idea. This is because hackers have prepared rainbow tables, which are basically just huge dictionaries mapping between well-known passwords and their hashes. So if they got hold of your database, they would still be able to work out the passwords from the hashes you have stored.
This is where salting comes in. Instead of hashing the password the user enters, you hash the concatenation of the password and the salt. So, a salt of "ABDE"
and a password of "mypassword123"
gets converted to "ABDEmypassword123"
, and it's that that goes through the hashing algorithm and the result is stored in the database when the user registers.
Later on, when someone tries to log in to the site, in order to re-do the hashing, you need to concatenate the same hash with the password that they enter when they log in. So they enter "mypassword123"
, you prepend "ABDE"
once again, "ABDEmypassword123"
gets hashed and compared to what's in the database, and you let them log in if it matches.
So, given all that, we can see the problem with changing the salt every time you restart the website:
- Initially the salt is, let's say,
"ABCD"
. Someone registers with password "mypassword123"
, and so "ABCDmypassword123"
gets hashed and stored in the database.
- Then, you restart your website. When it starts up, it has a new salt, let's say
"DEFG"
.
- The user comes along again, and tries to log in. They enter the correct password,
"mypassword123"
, and the new salt is added before it's hashed: "DEFGmypassword123"
.
- Because
hash("ABCDmypassword123") != hash("DEFGmypassword123")
, the website thinks they've entered the wrong password and won't let them in.
The solution? The salt value you use should be randomly-generated, and completely secret, but it should not change once you've deployed your site.
Hope that helps!