Our requirement is to store each password with a unique salt.
Looking at their old code, I see it uses RNGCryptoServiceProvider.GetNonZeroBytes.
The documentation says that it "Fills an array of bytes with a cryptographically strong sequence of random nonzero values."
That does not say that the salt is unique, though, does it.
Should I generate some data based on the time of day? Maybe a GUID? Or a combination of these?
Any suggestions?
Appropriate password-hash libraries usually generate the salt on their own, and include it directly into the hash-string, this is the recommended approach. A good example is BCrypt: https://www.nuget.org/packages/BCrypt.Net-Next/
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
string hashToStoreInDb = BCrypt.HashPassword(password);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from existingHashFromDb.
bool isPasswordCorrect = BCrypt.Verify(password, existingHashFromDb);
If you need to generate the salt on your own, the usual way is to read random bytes from the random source of the OS as you did in your example, or as is shown in this example from the DotNet documentation Rfc2898DeriveBytes.
The salt should be unique for each password, to prevent that a rainbow table can be used for more than one password. With a long random salt the chance is extremely small that you get the same salt twice. In the worst case, an attacker could use a rainbow table for two passwords instead of one, brute-forcing will still be faster.