Encrypt password fields in mongodb
According to the conversation in the comments, what you mean is hashing passwords, not encrypting passwords. You usually would do this with a salt to prevent a rainbow table attack. Storing passwords as salted hashes is the best practice standard when it comes to storing passwords in databases.
As of version 3.2, MongoDB has no native support for password hashing like some SQL databases provide, so you will have to implement it in Java.
To generate a new account or change the password of an existing account:
- generate a cryptographically secure random salt value with
java.security.SecureRandom
. This class works just like the standard random number generatorjava.util.Random
(it's a subclass) but trades performance for a much higher level of non-predictability which is required for a security-relevant context. - Create a string by concatenating salt and password
- Generate a hash of that string with a cryptographically secure hash function. There are many hash functions provided by Java out-of-the-box, but you want to use one which is intentionally hard to compute to slow down an attacker with database access trying to brute-force your hashes on their local supercomputer cluster. A good candidate is the "PBKDF2WithHmacSHA1" algorithm which is supported by the
javax.crypto.SecretKeyFactory
class. - Save the document to MongoDB with the fields
username
,password_hash
andpassword_salt
(plus your actual application data, of course). Do not save the original password.
To retrieve an account:
- Read the
username_input
andpassword_input
the alleged user entered into your login form. - Retrieve the document where the
username
matches theusername_input
the user provided. - Get the
password_salt
field from that document - Create a string by concatenating
password_salt
andpassword_input
just like you did before. - Generate a hash of that string with the same cryptographically secure hash function.
- Compare the hash with the
password_hash
field of the document. When it matches, the user entered the correct password.
You could alternatively only retrieve the password_hash and password_salt fields of the document and not load the rest before the user is authenticated, but I would assume that in the real world it will cause more load than it would save. Successful logins will usually greatly outnumber the unsuccessful ones, unless you have an attacker who tries to brute-force an account. And in that case you would block the attacker with fail2ban or another login-limiting mechanism.