Saving passwords in plain text should never be an option. Instead, we need to supply a one-way street to security by hashing passwords. We have previously explored that hashing alone isn’t adequate to moderate more involved attacks such as rainbow tables. A better practice for storing passwords is to include salt in the hashing handle. In other words, include extra arbitrary information to the hashing input that produces a secret word to make the hash one of a kind. The perfect verification stage would coordinate these two forms: hashing and salting consistently.
There are a bounty of cryptographic functions to select from such as the SHA2 family and the SHA3 family. One design issue with the Secure Hash Algorithm (SHA) families is that they were outlined to be computationally quick. How quickly a cryptographic method can generate a hash has a bearing on how secure and safe the password is.
Nowadays hardware, along with CPU and GPU, is very capable. It can compute millions or certainly billions of SHA-256 hashes per moment against a stolen database that makes Denial of Service (DoS), Distributed Denial of Service (DDoS), or repeated brute-force attacks so easy. We need an attempt that’s intermediate or moderate at hashing, i.e cracking passwords, to bring attackers nearly to a standstill. Moreover, we need this work to be versatile so that we will be ready to compensate for future quicker hardware by making the function run slower and slower over time.
Integrity and security of data is always one’s highest priority. BCrypt Algorithm is used to hash and salt passwords securely. BCrypt permits building a password security stage that can advance nearby hardware innovation to guard against dangers or threats in the long run, like attackers having the computing power to guess passwords twice as quickly. Let’s dive into the specifications and design that make BCrypt a cryptographic security standard.
Technology changes quickly. Expanding the speed, power, and control of computers can give advantage to both the engineers attempting to build program systems and the assailants attempting to misuse them. A few cryptographic programs aren’t outlined to scale with computing control. As clarified prior, password security depends on how quickly the opted cryptographic hashing method can calculate the password hash. A quick method would execute faster when running on much more capable hardware.
To moderate this attack vector, we may generate a cryptographic hash method that can be tuned to run slower in recently accessible hardware, i.e. the method scales with computing control power. Thus, within the plan of a cryptographic result for this issue, we must account for quickly advancing hardware and a steady length of the password.
BCrypt was first introduced by David Mazières and Niels Provos based on BlowFish Cipher. B stands for BlowFish & Crypt for the title of the hashing method utilized by the UNIX password framework.
Crypt may be an extraordinary case of disappointment in adjusting to technology changes. According to data provided by USENIX, in 1976, crypt could hash less than four passwords in one second. After twenty years, an optimized computer program, along with extraordinary hardware, was competent in hashing 200,000 passwords in one second utilizing that method!
As a case on how expanding the salt rounds (work factor) is directly proportional to the hashing time, I made a script in Node.js that calculated the hash of EDYu9943^%*_79 using a taken salt round from nine to fifteen.
Firstly, you have to install BCrypt through node package manager aka **npm **-
npm install bcrypt
Then, in any JavaScript file write that script of Node.js -
1
2
3
4
5
6
7
const bcrypt = require("bcrypt");
const plainText = "EDYu9943^%*_79";
for (let rounds = 9; rounds <= 15; rounds++) {
console.time(`cost = {rounds}, hashing time = `);
bcrypt.hashSync(plainText, rounds);
console.timeEnd(`cost = {rounds}, hashing time = `);
}
Output is -
1
2
3
4
5
6
7
cost = 9, hashing time = 65.683 ms
cost = 10, hashing time = 129.227 ms
cost = 11, hashing time = 254.624 ms
cost = 12, hashing time = 511.969 ms
cost = 13, hashing time = 1015.073 ms
cost = 14, hashing time = 2043.034 ms
cost = 15, hashing time = 4088.721 ms
In this, we produce salt and hash of plain text in different function invocations-
1
2
3
4
5
6
7
8
9
10
11
12
13
const bcrypt = require("bcrypt");
const saltRounds = 10;
const plainText = "EDYu9943^%*_79";
bcrypt
.genSalt(saltRounds)
.then(salt => {
console.log(`salt = {salt}`);
return bcrypt.hash(plainText, salt);
})
.then(hash => {
console.log(`hash = {hash}`);
})
.catch(err => console.error(err.message));
At the start, we define three variables. The first to import the BCrypt module and capture it in an alias named bcrypt, the second to define how many salt rounds are needed to hash. Here we note that the more salt rounds, the more the password will be hashed, and the more secure our password is. Here we are taking ten salt rounds and the third is the text we want to hash, in our case that is EDYu9943^%*_79.
Then we have to invoke the inbuilt function genSalt() of the BCrypt module and have to pass a number of salt rounds as an argument. If successful, in the “then” block we return the hash of text by again calling an inbuilt function hash of the BCrypt module.
In the first run this is what I get on my command line as output -
1
2
salt = $2b$10$ //DXiVVE59p7G5k/4Klx/e
hash = $2b$10$ //DXiVVE59p7G5k/4Klx/ezF7BI42QZKmoOD0NDvUuqxRE5bFFB
As we know we got the hash, i.e. $2b$10$//DXiVVE59p7G5k/4Klx/ezF7BI42QZKmoOD0NDvUuqxRE5bFFB.
Now, we are going to compare the given hash with the plain text we were given at the time of hashing to check if the hash is of that plain text password or not.
For this, we are going to use an inbuilt function of BCrypt module, “compare”, that takes plain text and hash as its arguments. If it matches, go into the “then” block, or else into the “catch” block.
1
2
3
4
5
6
7
8
9
const bcrypt = require("bcrypt");
const hash = "$2b$10$//DXiVVE59p7G5k/4Klx/ezF7BI42QZKmoOD0NDvUuqxRE5bFFB";
const plainText = "EDYu9943^%*_79";
bcrypt
.compare(plainText, hash)
.then(result => {
console.log("result = ", result);
})
.catch(err => console.error("error = ", err.message));