My understanding is that a salt is not intended to be secret, it is merely intended to be different from any centralized standard so that you can't develop a rainbow table or similar attack to break all hashes that use the algorithm, since the salt breaks the rainbow table. My understanding here might not be completely correct, so correct me if I'm wrong.
In a widely-used piece of open-source software, the salt would be widely known, and this opens you up to attacks because now they can simply attack the salted version of your hash and create rainbow tables that include the salt data.
As I see it, there are two options to deal with this. The first is to change the salt with every new version of the software, but this is no good because new versions of the software would no longer be able to test against old password hashes.
The second solution I thought of was to have a salt per password stored; in other words, each password gets a different salt. The downside is that the salts have to be associated with the password hashes in some way, probably just by sticking them right next to the password in the database. It might be even okay to use the username (it might not, though, probably usernames are too short).
My question is, is this acceptable? Is there any extra risk associated with storing the salt directly with the password it hashes? It seems to me that storing the salt in the source code is no different, so there's no security loss by storing the salt with the password.
DISCLAIMER: I'm not using this for any real life security system. In fact, I have never designed a password system of any kind. I'm just keeping myself vaguely educated about security issues.
Using a single salt for all passwords in the database is helpful, but much less secure than giving each user a unique salt.
Basically: a longer (in bytes) password+salt increases the search space, and thus makes it harder to use "stock-standard" rainbow tables.
However, if the same salt is used for all entries, then it is possible to create a rainbow table specifically to attack your software. If your userbase is large then someone might decide to make such a rainbow table.
For example, if you simply add " and a lot of salt" to the end of each password before hashing, an attacker could construct a table of hash values generated by lots of strings, all those strings ending with " and a lot of salt".
For this reason, a per-user salt is the best way to go. However, remember that you also want the password+salt to be "long".
If you want to use the primary key, it's probably a good idea to take the hash of the primary key rather than using the primary key itself, because if the password+salt for user 43 looks like "myPassword00000000043" then an attacker could build a table with the assumption that there are a lot of zeroes in the middle. Creation timestamps and random string are probably better options though, as PKeys can sometimes be easily found or guessed.
Note: I'm not a true encryption expert, don't use this advice in a real system.