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
Top comments (2)
Violation of rule #1 of cryptography:
Never ever invent your own crypto algorithm.
Crypto is difficult, really difficult.
Hashcat can do 25Giga-hashes per second for MD5. Only 13000 hashes per second for bcrypt with the cost parameter set to 5 (at this point 12 is advised, which is 2^7 more slower). So even if you would do a million rounds in the above algorithm you do not come close to bcrypt's security. Also, I have no idea if doing multiple rounds of md5 makes it more secure.
Just use bcrypt, it is battle tested and still secure.
Thanks for your feedback. However, if you read through the article, you would have observed that I stated clearly the intent.
Also, before the Conclusion, there's a disclaimer
I hope this helps explain better.