8

I have following code, it insert the userName and password into database but the password is stored in plain text format. I mean when I'll look into the db I can see the inserted password.

I want to store password in encrypted format

MongoClient client = new MongoClient("localhost",27017);
DB db = client.getDB("Test");
DBCollection collection = db.getCollection("EncryptionDemo"); 
BasicDBObject documentDetail = new BasicDBObject();
documentDetail.put("userName", "admin12");
documentDetail.put("password", "12345");
collection.insert(documentDetail);

How can I achieve this?

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
PVH
  • 83
  • 1
  • 1
  • 5
  • The encryption have to be done in Java coding. Have a look at password encryption techniques - PBKDF2 or bcrypt or scrypt – The Coder Mar 09 '15 at 06:25
  • So use method to encrypt the string. Databases just store what you ask them to. There is no "encrypted" type of field and MongoDB is "schemaless", so there are no "field types". That's for your code to implement. – Neil Lunn Mar 09 '15 at 06:26
  • 2
    You don't want to encrypt the password but hash it - big difference. [https://crackstation.net/hashing-security.htm](https://crackstation.net/hashing-security.htm) is a guide how to do it properly. – jHilscher Mar 09 '15 at 06:30
  • @user1354678 - You mean we can't encrypt password field at mongodb side, We need to handle it at java side – PVH Mar 09 '15 at 06:51
  • Ofcourse, I didn't see any DB which is capable of auto encrypting or hashing the user passwords before saving, we've to do it with a good technique at java side and set the hashed or encrypted password in the respective object for inserting or updating process. I would recommend password Hashing instead of encrypting. – The Coder Mar 09 '15 at 06:56
  • @user1354678 All major SQL databases have some kind of function for hashing and many have functions for AES encryption through SQL-queries. – Artjom B. Mar 09 '15 at 07:03
  • @user1354678 - As per you suggest I have tried PBKDF2 hashing technique, and it is working fine. Password is inserted into DB like encrypted but it is hashed. Now when I want to check particular actual password, How can I get it back in original format. – PVH Mar 09 '15 at 07:18
  • @jHilscher What you say is valid in most cases. But MongoDB could not care less if the value was effectively "binary" and will just store it correctly without any special treatment. So a big difference for a strict schema datastore, but no difference for a datastore without any concept of schema. – Neil Lunn Mar 09 '15 at 10:11
  • Hash the password which is entered during login, then check whether that hash is equal to the hash stored in DB. You're also storing the salt in the DB right? You can't make it working if you don't store the salt used for hashing in DB – The Coder Mar 09 '15 at 10:18

2 Answers2

17

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:

  1. generate a cryptographically secure random salt value with java.security.SecureRandom. This class works just like the standard random number generator java.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.
  2. Create a string by concatenating salt and password
  3. 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.
  4. Save the document to MongoDB with the fields username, password_hash and password_salt (plus your actual application data, of course). Do not save the original password.

To retrieve an account:

  1. Read the username_input and password_input the alleged user entered into your login form.
  2. Retrieve the document where the username matches the username_input the user provided.
  3. Get the password_salt field from that document
  4. Create a string by concatenating password_salt and password_input just like you did before.
  5. Generate a hash of that string with the same cryptographically secure hash function.
  6. 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.

Philipp
  • 67,764
  • 9
  • 118
  • 153
0

I guess this question is old but it seems there now supports fields-level encryption. This method works significantly differently than password field hashing in mysql. Also, part of the mongodb field-level encryption functionality is not available for free.

Yehuda Clinton
  • 375
  • 4
  • 12