1

I've been reading the pros and cons of using hash vs encryption when storing sensitive data on a MySQL database, and the arguments from both sides by people who favor either hash or encryption have only left me in confusion and uncertainty on which one to use.

Hash:

"INSERT INTO users (`id`,`username`,`password`) VALUES("Bob",SHA2("password1234"));"

CONS:

  • Deprecated

  • Rainbow Tables

Encryption:

"INSERT INTO users (`id`, `username`, `password`) VALUES ("Bob", aes_encrypt("password1234", "key1234"))";

CONS:

  • May not work for some collation types

  • The key may be compromised

  • Rainbow Tables

So which is really more ideal in terms of providing security and performance (fast read and retrieval from database)? (In a table of approx 1,000 - 5,000 rows).

Jae Bin
  • 49
  • 1
  • 2
  • 10
  • There is no confusion, uncertainty, or problem. Hashing is the only way. Encryption is reversible and you never ever want to be able to get the plaintext password. – Sami Kuhmonen Oct 12 '18 at 05:30

1 Answers1

8

I'm going to go ahead and say neither of them. You should never store a password, even encrypted. That makes you vulnerable to password stealing, either external or internal to your organization. Also, SHA2 is not deprecated per-se, and you don't specify the hash length. SHA2-512 or even SHA2-256 are still considered excellent cryptographic hashes. You could also use the more recent SHA3/Keccak crytographic hash, but from recent literature, it's not better than SHA2 as much as different. Both are still endorsed by NIST.

However, there's consensus in InfoSec that a simple crypto hash is not enough for properly storing secrets. As of 2018, it seems either PBKDF2, bcrypt or ARGON2 are widely considered the top contenders for "best" crypto hash algorithms. You can read a much more detailed explanation about passwords and cryptographic hashes on this Security StackExchange link https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords/31846#31846

The link above doesn't explain ARGON2, which was the recent winner of the Password Hashing Competition. You can read more about it here: https://github.com/p-h-c/phc-winner-argon2

My recommendation would be to:

  • Add a fourth field to the table called salt. This should be a truly random 8+ digit alphanumeric string, stored in plaintext.
  • Store the "password" as CryptoHash(salt + 'password1234'). This protects you from rainbow tables, since it's not feasible to precalculate ALL rainbow tables for all possible salts.

Replace CryptoHash above with either PBKDF2, bcrypt or ARGON2, and you'll have a pretty good password storage mechanism.

mjuarez
  • 16,372
  • 11
  • 56
  • 73
  • This is a really good option imo. The ideal password is random (the user never usually make a random password themselves) and 9 characters long and consists of at least 2-3 numbers as well, which is where the salt comes in. That ensures a 9 length (or more) password that is random. Then a proper hash is needed on top of that, and since argon2 won the PHC, we can only assume that that's the best option to go with. Now, even if you use 4 RTX gfx, running hashcat, it's gonna take a significant amount of time to crack this one. – Martin Oct 12 '18 at 06:29
  • However if quantum computers ever becomes available to the general public (which it probably will in due time), that's gonna be a big yikes. – Martin Oct 12 '18 at 06:33
  • 1
    Most implementations of password-hash functions (BCrypt, SCrypt, Argon2) create the salt on their own and store it in the resulting hash string, so there should be no need for an extra field in the database. – martinstoeckli Oct 12 '18 at 10:52
  • @martinstoeckli Would you recommend storing the Bcrypt hash in the database as it is or should it be hashed one more time using SHA-256 when storing it in the database? – Jae Bin Oct 12 '18 at 20:09
  • @JaeBin - Just store the BCrypt hash string in the database. To verify a password, the function needs to extract the used algorithm, the cost factor and the salt from the string (see another [answer](https://stackoverflow.com/a/20399775/575765) for more details). This makes the password-hash function future proof, it can e.g. change the algorithm or the cost factor if necessary, but this is not possible if you do additional hashing. – martinstoeckli Oct 13 '18 at 09:00
  • @martinstoeckli Hi, just one more thing: would adding an encryption to the BCrypt hash before storing it in the database add any drastic level to security or not really? – Jae Bin Oct 13 '18 at 21:53
  • @JaeBin - No, encrypting after hashing allows to exchange the key, whenever this should be necessary, encrypting before hashing doesn't. Encrypting twice doesn't add anything, because it is the privileges on the server to get the key, which adds the security, this doesn't change with double encryption. – martinstoeckli Oct 14 '18 at 18:09