I am currently writing a program and part of it involves securely creating password hashes to store in a database and I came across the phpass framework, which seems to be highly recommended. In phpass, they seem to go through great lengths to produce a salt that is as truly random as possible to be used for the hashes (e.g. reading from /dev/urandom).
My question is, what is the benefit of doing this as opposed to simply using uniqid()
? Isn't the point simply to make sure that the salts used for the hashes are different from each other rather than random? Wouldn't using a truly random salt actually be worse than using a unique salt since it could potentially produce collisions while uniqid() won't?
Edit: My question wasn't about whether or not "true" randomness exists in computer environments, so maybe I misphrased it a bit, however my question was more along the lines of whether a "more" random salt has any benefit over more uni开发者_如何转开发queness as a salt.
I'm trying to find references to some precedents of exploits (and struggling!), but the idea of a cryptographically random salt as opposed to a random value such as produced by uniqid() is to help protect against attacks on the encryption scheme by way of the ciphertext. A salt with a predictable pattern - such as a unique ID - generated by a pseudo-random number generator takes some of that variability out of the ciphertext and of course, in cryptography, unpredictability is what you're looking for.
Certainly if a cryptographically-secure random number generator is available to you in your framework of choice (i.e. RNGCryptoServiceProvider in .NET), you'd opt for this over more predictable patterns. I'll see if I can find some good precedents or white-papers on this.
In PHP, the uniqid()
function calculates its result based on the current time. This helps ensure that the values are unique because no two times occur twice, however this does not work across multiple servers since it is purely time-based. Using something time-based is bad because the number of different values that can be produced by uniqid()
are very limited. Assuming that PHP has been in use for 25 years, this calculates to 7.89e+14 microseconds that have passed and therefore the same number of values for uniqid()
would have been produced.
This is a very large number, however assuming that we are able to get a truly random salt, the chance of a collision is actually far less than when using uniqid()
. The possible characters that can be used as a salt are:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
That means we have 64 different characters to use for a 22 characters long salt, which calculates to roughly 5.44e+39 different combinations.
So basically, in trying to make something unique, it is actually less unique than it would be if a random source were used.
Mike, as I said in my another answer, I wouldn't think this is an issue with salts, but if you are really concerned about true/pseudo randomness, you can use numbers from random.org. See the difference, a and see how to get true random number in PHP.
I think it doesn't matter as the salt must be also stored alongside with the hashed password, so the attacker will get the salt anyway and the attack will be the same, regardless HOW did you generate the salt.
(OT discussion: I argued that I don't see big advantage of using salt for storing passwords - once the attacker gets salt for particular hashed password, he can do dictionary attack anyway ... it will be slower, because the attacker must rehash the dictionary for each password salt, but.. md5() is fast as hell and if the attack takes 5 minutes or half day, what's the real difference... I don't feel much safer with salt than without.)
EDIT - discussion conclusion: salt makes a big difference in time needed to crack the passwords, but don't use md5() for hashing passwords! Use very slow hashing function like bcrypt() or, if you need to use md5(), call it many thousand times!
精彩评论