TL; DR – You can save the salt in plain text without obscuring or encrypting it, but do not just pass it on to someone who wants it.
The reason we use salts is to stop pre-calculation attacks like rainbow tables. These attacks create a database of hashes and their plaintext so that hashes can be searched for and immediately converted to plain text.
Most tables also contain a list of common passwords:
* I'll use SHA-1 as an example, but later explain why this is a bad idea.
So if my password is hash
9272d183efd235a6803f595e19616c348c275055It would be extremely easy to search for it in a database and find out if it is plain text
bacon4, Instead of spending a few hours cracking the hash (in this case it would take a few minutes on a decent GPU, but we'll talk about that later), you'll get the result immediately.
Obviously that's bad for security! So we use a salt. A salt is a random unique token that is stored with each password. Let's say the salt is
5aP3v*4!1bN and the hash is
9537340ced96de413e8534b542f38089c65edff3, Now your database of passwords is unusable because nobody has rainbow tables that contain this hash. It is mathematically impossible to generate rainbow tables for every possible salt.
Now we've forced the bad guys to crack the hashes again. In that case, it would be pretty easy to crack because I used a wrong password, but it's still better than he can look it up in a tenth of a second!
Now there is the goal of the salt just To prevent pre-generated databases from being created, they do not have to be encrypted or hidden in the database. You can save it in plain text. The goal is to force the attacker to crack the hashes as soon as he gets the database instead of looking them up in a rainbow table.
There is a limitation, however. If the attacker can quietly access a salt In front Burglary into your database, eg. Through a script that offers salt to anyone who asks, he can create a rainbow table for that salt as easily as possible, if there were none. This means that he can silently take the salt of your administrator account and create a nice big rainbow table, then hack into your database and log in immediately as an administrator. This will not give you time to determine that a violation has occurred and no time to take action to prevent damage, such as: Change the administrator password / lock privileged accounts. This does not mean that you should disguise your salts or try to encrypt them, but that you should design your system so that they can access the salts only when you enter the database.
Another idea to consider is a pepper. A pepper is a second salt that is constant between individual passwords but is not stored in the database. We could implement it as
H(salt + password + pepper), or
KDF(password + pepper, salt) for a key derivation function - we'll talk about that later. Such a value could be stored in the code. This means that the attacker must access both the database and the source code (or the Webapp binaries in the case of ASP .NET, CGI, etc.) to try to crack the hashes. This idea should only be used to complement other security measures. A pepper is useful if you are concerned about SQL injection attacks where the attacker only has access to the database, but this model becomes (slowly) rarer when parameterized queries are executed. You are with parameterized queries, right? Some argue that a pepper is safety through darkness, since you only cover the pepper, which is something true, but it is not to say that the idea is unfounded.
Now we are in a situation where the attacker can force every single password hash, but can no longer search for all hashes in a rainbow table and immediately recover plaintext passwords. How can we prevent brute force attacks?
Modern graphics cards contain GPUs with hundreds of cores. Each core is very good at math but not very good at decision-making. It can do billions of computations per second, but it's pretty awful to do operations that require complex branching. Cryptographic hash algorithms fit into the first type of calculation. As such, frameworks such as OpenCL and CUDA can be used to massively accelerate the operation of hash algorithms. If you run oclHashcat with a decent graphics card, you can calculate more than 10,000,000,000 MD5 hashes per second. SHA-1 is not much slower either. There are people with dedicated GPU cracking rigs that contain 6 or more top-end graphics cards, resulting in a cracking rate of over 50 billion hashes per second for MD5. Let me put this into context: Such a system can forcefully force an 8-digit alphanumeric password less than 4 minutes,
It's clear that hashes like MD5 and SHA-1 are way too fast for this type of situation. One approach is to do thousands of iterations of a cryptographic hash algorithm:
hash = H(H(H(H(H(H(H(H(H(H(H(H(H(H(H(...H(password + salt) + salt) + salt) ... )
This slows down the hash calculation but is not perfect. Some advocate the use of SHA-2 family hashes, but this does not provide much extra security. A secure approach is to use a key derivation function with a work factor. These functions require a password, a salt and a work factor. With the work factor, you can tailor the speed of the algorithm to your hardware and security needs:
hash = KDF(password, salt, workFactor)
The two most popular KDFs are PBKDF2 and bcrypt. PBKDF2 performs iterations of an encrypted HMAC (although it can use block ciphers), and bcrypt calculates and combines a large number of cipher text blocks from the Blowfish block cipher. Both do about the same job. A newer version of bcrypt, scrypt, works on the same principle, but introduces a memory-intensive operation that makes cracking GPUs and FPGA farms completely impossible due to memory bandwidth limitations.
To update: As of January 2017, Argon2 is the newest hashing algorithm of choice, winning the Password Hashing competition.
Hopefully this will give you a good overview of the password storage issues and will answer your salt storage question. I strongly recommend reading the "Links of Interest" at the end of Jacco's answer, as well as the following links: