For the sake of security, I had to implement a seeded-hash system to secure passwords in a database. While straight-forward hashes are good for ensuring that passwords are not stores in clear text, they are still vulnerable to rainbow-table attacks. A seeded hash helps to reduce this risk.
However, the question occurred on how to actually do a seeded hash. I got my apprentice to look around and we finally found a useful scheme. The seed and password are usually concatenated before being hashed.
hash = Hash(seed + password);
However, if the seed was fixed, then it does not really help much because it would still be susceptible to rainbow attacks if the secret seed ever got out. So, we had to use a random seed. However, a random seed would generate all manners of rubbish unless we could somehow embed the seed in the hash.
Since this was part of a password storage scheme, it would be perfectly alright to embed the seed with the hash because the size of the hash result is fixed. So, any extra data stored with the hash result would be the seed. We could convert everything to Base64 to store it in clear-text on the server. This was the scheme that we used in the end:
seededhash = Base64(Hash(seed + password) + seed);
This way, to do a password match, the application would need to decode the Base64, separate the seed from the hash and then perform the hash operation on the supplied password with the seed to see if it matched the hash.
Caveat: this solution only works in the situation of password matching – where we already know exactly which record to match against and merely need to verify that the information provided is accurate. This would not be useful for indexing purposes, like that used in Git. In such a scenario, straight-forward hashing would still need to be done.