|
| 1 | +## Fist, What is password hashing? |
| 2 | + |
| 3 | +hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 |
| 4 | +hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366 |
| 5 | +hash("waltz") = c0e81794384491161f1777c232bc6bd9ec38f616560b120fda8e90f383853542 |
| 6 | + |
| 7 | +Hash algorithms are one way functions. They turn any amount of data into a fixed-length "fingerprint" that cannot be reversed. They also have the property that if the input changes by even a tiny bit, the resulting hash is completely different (see the example above). This is great for protecting passwords, because we want to store passwords in a form that protects them even if the password file itself is compromised, but at the same time, we need to be able to verify that a user's password is correct. |
| 8 | + |
| 9 | +The general workflow for account registration and authentication in a hash-based account system is as follows: |
| 10 | + |
| 11 | +1> The user creates an account. |
| 12 | + |
| 13 | +2> Their password is hashed and stored in the database. At no point is the plain-text (unencrypted) password ever written to the hard drive. |
| 14 | + |
| 15 | +3> When the user attempts to login, the hash of the password they entered is checked against the hash of their real password (retrieved from the database). |
| 16 | + |
| 17 | +4> If the hashes match, the user is granted access. If not, the user is told they entered invalid login credentials. |
| 18 | + |
| 19 | +5> Steps 3 and 4 repeat every time someone tries to login to their account. |
| 20 | + |
1 | 21 | ### bcrypt works in 2 steps, first genSalt and then hash the password with that salt
|
2 | 22 |
|
3 | 23 | ### The regular steps are >> Generate the salt first (if err throw err else give me the salt)
|
@@ -133,3 +153,42 @@ router.post('/login', (req, res) => {
|
133 | 153 | The salt is incorporated into the hash (as plaintext). The compare function simply pulls the salt out of the hash and then uses it to hash the password and perform the comparison.
|
134 | 154 | When a user logs into our system, we need to check that the password entered is correct. Unlike other systems that would decrypt the password in the database (if it is encrypted), and compare it with the one entered by the user, what we do with bcrypt is encrypt the one entered by the user. To do this, we will pass the password to bcrypt to calculate the hash, but also the password stored in the database associated with the user (hash). This is because, as mentioned before, the bcrypt algorithm used a random segment (salt) to generate the hash associated with the pasword. This was stored along with the password, and you need it to recalculate the hash of the password entered by the user and finally compare with the one entered when registering and see if they match.
|
135 | 155 |
|
| 156 | +Looking at the [source code of bcrypt.compare](https://github.com/dcodeIO/bcrypt.js/blob/b09f7f266a7015456b7b36deeb026dc636f64542/dist/bcrypt.js#L269) function makes the above steps clear |
| 157 | + |
| 158 | +```js |
| 159 | +bcrypt.compare = function(s, hash, callback, progressCallback) { |
| 160 | + |
| 161 | + function _async(callback) { |
| 162 | + if (typeof s !== "string" || typeof hash !== "string") { |
| 163 | + nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof hash)))); |
| 164 | + return; |
| 165 | + } |
| 166 | + if (hash.length !== 60) { |
| 167 | + nextTick(callback.bind(this, null, false)); |
| 168 | + return; |
| 169 | + } |
| 170 | + bcrypt.hash(s, hash.substr(0, 29), function(err, comp) { |
| 171 | + if (err) |
| 172 | + callback(err); |
| 173 | + else |
| 174 | + callback(null, safeStringCompare(comp, hash)); |
| 175 | + }, progressCallback); |
| 176 | + } |
| 177 | + |
| 178 | + if (callback) { |
| 179 | + if (typeof callback !== 'function') |
| 180 | + throw Error("Illegal callback: "+typeof(callback)); |
| 181 | + _async(callback); |
| 182 | + } else |
| 183 | + return new Promise(function(resolve, reject) { |
| 184 | + _async(function(err, res) { |
| 185 | + if (err) { |
| 186 | + reject(err); |
| 187 | + return; |
| 188 | + } |
| 189 | + resolve(res); |
| 190 | + }); |
| 191 | + }); |
| 192 | + }; |
| 193 | + ``` |
| 194 | + |
0 commit comments