A Simple Password Hash implementation
Tags: node, express, javascript
Published: 2019-08-09 15:41:06

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](https://www.npmjs.com/package/bcrypt), [password-hash](https://www.npmjs.com/package/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:

```javascript
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](https://en.wikipedia.org/wiki/Salt_(cryptography))

### 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](https://whatis.techtarget.com/definition/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`

```javascript
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](https://www.oriechinedu.com/posts/simple-password-hash-implementation/)_