A Simple Password Hash implementation
dev.to

Passwords are not stored as plain text for obvious security reasons. There are several npm packages already in place for password encryption such as bcrypt.js, password-hash etc.

This article does not aim to provide a better solution to the ones already provided by the existing libraries, rather it tends to shed some light on how the implementation works under the hood.

   Getting Started

I assume that you already created a project. Now go ahead and create a file named custom-bcrypt.js.

Copy the snippet below into the custom-bcrypt.js file:

const md5 = require("md5");module.exports = {
  /**
   *
   *
   * @param { string } rawPass - the password to be hashed
   * @param { object } [options={}] - object containing salt and rounds
   * @returns {string} 
   */
  hash(rawPassword, options = {}) {
    /**
     * salt is optional, if not provided it will be set to current timestamp
     */
     const salt = options.salt ? options.salt : new Date().getTime();
    
    /**
     * rounds is optional, if not provided it will be set to 10
     */
     const rounds = options.rounds ? options.rounds : 10;
     
     let hashed = md5(rawPassword + salt);
     for (let i = 0; i <= rounds; i++) {  
         hashed = md5(hashed);
     }
     return `${salt}$${rounds}$${hashed}`;
  },
  /**
   *
   *
   * @param {string} rawPassword - the raw password
   * @param { string } hashedPassword - the hashed password
   * @returns
   */
  compare(rawPassword, hashedPassword) {
      try {  
          const [ salt, rounds ] = hashedPassword.split('$');  
          const hashedRawPassword = this.hash(rawPassword, { salt, rounds });  
          return hashedPassword === hashedRawPassword;
      } catch (error) {  
          throw Error(error.message);
      }
  }};

Let's us explain what's going on in the code snippet above.

First, notice that we required md5 library which forms the base for the hashing. Now, install md5 in the project.

npm add md5 or yarn add md5

   Salt

In cryptography, a salt is random data that is used as an additional input to a one-way function that "hashes" data, a password or passphrase. Salts are used to safeguard passwords in storage. Salts defend against a pre-computed hash attack. - wikipedia

   Rounds

The rounds specify the number of iterations used in the hashing. The higher the rounds the more difficult it is for hackers to guess the password using rainbow table.

Notice that in the custom-bcrypt module above, we have two functions hash and compare.

   hash function

The hash function takes two arguments, the password to be hashed and the options object which is set to an empty object by default. The options object has two optional properties the salt and the rounds which are set to the current timestamp and 10 respectively. This function uses md5 to encrypt the password plus the salt as many times as the rounds. The returned value is a string consisting of the salt, rounds and the hashed value all concatenated together.

   compare function

The compare function takes two arguments, the raw password to be verified and the previously hashed password. It extracts the salt and rounds from the previously hashed password and then uses it to hash the current raw password and returns a corresponding Boolean value for whether the password matches or not.

Now, let's test our custom bcrypt module. Create a file named sample.js.
Copy the code below into the sample.js

const bcrypt = require('./custom-bcrypt')
const rawPassword = 'password'

console.log(bcrypt.hash(rawPassword))
//1563995248971$10$58e0867f3acc11de363e03389bb27167

console.log(bcrypt.compare('password','1563995248971$10$58e0867f3acc11de363e03389bb27167'));
//true

console.log(bcrypt.hash(rawPassword, {salt: 'someRandomString', rounds: 20}))
//someRandomString$20$199d9de71859a87cdd22e52d93f4522a

console.log(bcrypt.compare('password', 'someRandomString$20$199d9de71859a87cdd22e52d93f4522a'));
//true

You can test it how ever you want, for the sake of this article, I tested it on the terminal using node sample.js.

Disclaimer: This article does not guarantee the security of encryption implemented herein.

   Conclusion

In this article, we tried to shed some light on how password encryption works. Feel free to reach out to me if you have any question or contribution to this article. ✌️

This article was originally published on my blog