Is it okay to use the primary key as the salt in a Users table?
The only disadvantage that I can see is if the PK changes (unlikely), then the passwords break.
What are your thoughts?
I see no immediate problems with that approach. Especially if you use a per website salt in addition to a per user salt. So that your combined salt is complex enough. The main function of a salt in password hashing is preventing rainbow tables. And you don't need a highly random salt for that.
I still wouldn't do it that way, since using a random salt is standard practice. And inventing your own crypto is usually a bad idea, because it's easy to get wrong. So I'd simply follow the standard practice unless there is a really good reason not to.
IMO it's more important to use a KeyDerivationFunction with enough iterations to slow down brute-force attacks than to worry about the randomness of your salt. Having some salt is essential, but only one of the things you need.
Salt should always contain random bits generated by a cryptographically sound method. The primary key is anything but random; don't do it!
EDIT: What I am getting at here is that your primary key on its own won't contain enough entropy. It's possible to generate a separate rainbow table for each salt value. Your salt needs to contain enough bits of entropy such that it's infeasible to generate enough tables to enable an attacker to precompute your hashes.
|show 3 more comments|
It can be acceptable, in a few rare occasions, but even then it is unlikely to offer any real benefits. Basically, don't do this.
The situations where it might be okay are where the primary key is a) a large value, and b) a random value. A somewhat contrived example of this might be were a UUID Type 4 is used as primary key.
The only benefit you would get from this is saving a few bytes per user. This is completely negligible, no current database engine would even notice this saving -- even if you have millions of users.
However, there are major drawbacks to using the primary key as a salt, in the areas of software development needs and security:
In software development:
Final answer: It depends on what you are actually using for primary key. But in almost all cases, this is a bad idea.
It definitely not OK. Use a random salt for each user. Use blowfish (the standard) or something equivalent.
In addition to accepting a random salt, blowfish is adaptive, meaning you can make it lengthier to compute as CPUs get faster.
Edit: sorry, got it wrong: I thought of "primary key" as a kind of server private key (e.g. in a HTTPS context), not in the database-SQL meaning. However, the database primary key is still unique in that database but if the software is used in several distinct server installations then the same "primary key" values will most probably occur in all of them. So a random (long) salt is still to be preferred, security-wise (randomness ensures uniqueness with high probability, if the salt is big enough, e.g. 16 bytes or more).
Not good. The salt shall be unique per instance: each hashed password for each user should have its own salt value. That's the whole point of the salt: to be such that each password is hashed with a specific scheme, distinct from the way other passwords are hashed, so that an attacker cannot share attack costs across several attacked passwords.
On the other hand, the salt needs not be secret (otherwise it would be called a "key"). It is conceivable to have a password hashing scheme which depends on a key (basically, a MAC) but this involves a different threat model, in particular with key management, which is known to be a difficult problem. Use a per-password random salt, stored along the hashed password, with no key whatsoever, and you will be happier.
I would not recommend using the primary key as the salt. That practice is brittle.
Good designs should be robust-under-maintenance. Systems are not static; we often need to maintain them over time, to add new features, fix bugs, improve performance, etc.
Using the primary key as the salt is poor practice because it makes security reliant upon something that it is out of our control. There's no guarantee that a primary key will be unpredictable and have sufficient entropy for a salt; the requirements for a salt (uniqueness across sites, unpredictable) are different from and a superset of the requirements for a primary key (uniqueness within a single database). Using a primary key for a purpose which it wasn't designed for seems imprudent.
Even if using the primary key as salt happens to be secure when initially implemented, it would be easy for it to silently become insecure at some point in the future, as the software is maintained. Suppose the database or application changes how it chooses primary keys. That might not affect database correctness, and might seem like an innocuous change to some database designer or software developer, but it could subtly reduce the security of your password salting.
To be clear, I don't view this as an egregious violation. If I saw it in an existing application, I wouldn't jump up and down to fix it now, now, now. But if you're writing a new application, it seems like poor practice and I wouldn't recommend it. It is too clever by half.