I'm investigating whether I can use bcrypt not just for password hashing, but to encrypt database contents as well.
The idea would be to run a strong password through bcrypt (with an appropriately high work factor, so that the operation takes perhaps 10ms), and then use the digest created as a symmetric key to encrypt the database record.
I would obviously NOT store the digest in the database; rather, to authenticate the user, I'd decrypt their database entry and verify that it was correct (something cheap like checking the first few bytes for a known value, for instance).
I would certainly store the work factor and the salt, as those would be needed to re-hash the provided password and generate the symmetric key.
It looks like bcrypt outputs a 186-bit hash (31 base64 chars, and I don't know why it says 184 bits here: http://stackoverflow.com/questions/5881169/storing-a-hashed-password-bcrypt-in-a-database-type-length-of-column).
Not sure if it would it be safe to pad that out and use 192-bit AES as my symmetric algorithm... or is there something insecure about that which I don't realize? Would it make sense to use a different algorithm?
Would love some feedback on whether this scheme makes sense, whether there's something better to do, and any pointers to additional reading.
Unlike bcrypt, PBKDF2 was explicitly designed for this purpose, so I'd recommend using that if you do go this route. It'll also get you a strong 256-bit key (in the correct variant). (If you really want to use bcrypt, just truncate at 128 bits and use AES-128, which is good enough. Really.)
Whether using bcrypt or PBKDF2, you'll want to use a salt, which should be stored in the database. Whether using bcrypt or PBKDF2, some users will choose pitifully weak passwords and allow their data to be decrypted (no password hash can save you if you pick "password" or "iloveyou"). You can more-or-less solve this by integrating e.g. http://www.openwall.com/passwdqc/.
All that said, I'm not sure this is a good idea:
- you expose yourself to DDoS by repeated logins, fixable only by setting the work factor for bcrypt/PBKDF2 dangerously low (100 POST "/create_new_account.php" requests per second is not much);
- if your front-end machines are compromised, the attacker can gather passwords from legitimate logins, so you still need to secure your front-end machines;
- encrypting everything that could be useful to an attacker means that you can only use your RDBMS as a networked hash table;
- crypto is hard, and easy to get subtly wrong.
Then again, implementing this would most likely increase your security quite a bit. Just don't rely on it.