The usual method for simple sites is to store a hash of a user's password right in their user record.

What if the password field is removed from the user table, and a password table is created? The password table would have the same password hash, but instead of the user id, the key to the table is another hash - a hash of the userid and some secret key.

The idea being that if you get a copy of the user table, you don't get the password hashes. If you get the user and the password table, you cannot connect a password to any particular user account.

I suppose if you could crack the password hash, you'd have a handful of passwords you know are in use on the system. You could try each password on each account until it works. So perhaps I answered my own question. Nevertheless is there something I'm missing? This feels like a good idea, but I couldn't find any thing about it.

I suppose that it might be easy to detect an attack that is using a list of passwords that do exist for users in the system and block or otherwise shutdown the attack.

  • 1
    And where do you propose the secret key be stored? If it's on the server, why should the hypothetical "hacker" not be able to get a hold of it if it can access the password and user tables?
    – Thomas
    Dec 14, 2012 at 15:20
  • well, let's assume for the sake of the idea, that the db is compromised/copied but the code/config is not.
    – changokun
    Dec 14, 2012 at 18:44

5 Answers 5


If you use an appropriate cryptographic password hashing function (e.g., bcrypt, scrypt, or PBKDF2), the value added by this approach is negligible. So, really, the solution is simply to responsibly hash your passwords in the first place.


Take a look at my answer here talking about segregating password information. Combined with a different permissions set that doesn't allow reading but does permit comparison by means of a stored procedure, separation of password information would indeed be useful.

You can't effectively go about encrypting or hashing key values because the output would be random. You'd either need a large enough space to avoid collisions and then you'd run into painful amounts of database fragmentation where insertions are happening all over the place and pages being split. Key values should remain incrementing integers for everybody's sanity.

I suppose that it might be easy to detect an attack that is using a list of passwords that do exist for users in the system and block or otherwise shutdown the attack.

No. That would involve checking against the full list of possible hashes which would be expensive if you've used proper salting and hashing methods.

  • You can't effectively go about encrypting or hashing key values because the output would be random. True for hashing, but encrypted keys would be unique.
    – jdigital
    Dec 18, 2012 at 1:37

If you are salting and hashing your passwords properly, there is little to no value added by the system you propose. If an attacker can get one database, they can probably get both. An added hash on the foreign key does not provide any appreciable increase in security beyond the hashing of your passwords.

Additionally, depending on how you implement such a system, it could cause substantial performance losses.


This is security by obscurity, IMO. The extra step of hashing the user ID to produce a password is trivial to recreate once it's known. Because the usernames aren't stored in hashed form in your user table, and because something, somewhere, has to have read access to both DBs, if an attacker can obtain a dump of your user table and get usernames, he can obtain a dump of the password table as well and connect the dots. The only unknown is the hashing algorithm used, and because there are a small number of secure hash functions suitable for the purpose, it's trivial to just try them all (and don't think for a minute that I'm advocating creating your own hash or using an obscure one; that's just more security by obscurity).

If the hashing method is secure and the password has non-trivial entropy (the top 10 most common passwords and simple derivations of same have effectively zero entropy as they're the first thing any cracker will try), you could spray-paint your password hash on your car and drive it into the middle of DEF CON and you'd be perfectly fine. That's the point; the ideal hash's most efficient attack should be the birthday attack, which should still be infeasible with the proper combination of input entropy, digest size and computational cost.


We hash passwords for a specific reason: in case an attacker could grab a copy of your server tables. We hash passwords to prevent the attacker from escalating a partial, read-only access into a read-write access (see this blog post for a more detailed discussion). Password hashing is already a second layer of defence.

Your proposal is about adding a third layer: it has value only if the attack scenario is that the attacker could obtain a read-only access on one table but not on both. This scenario is not very realistic, though, because such read-only access often come from SQL injection attacks, and server elements which have the permission to read the table of users often have the permission to read the hashed password as well (in particular the login system, which must, by definition, use both).

So you have to balance the extra safety against the extra complexity, because complexity is known to be the arch-enemy of security. In that case, I don't find the extra complexity to be worth it, since the scenario for which the table splitting would add some safety is implausible.

You must log in to answer this question.