- [Instructor] As promised, I will now tell you
a little bit more about password encryption.
For that, let's first try to create the user.
So I add new user, john@acme.com.
And I give him a password and I hit Submit.
So let's look into MongoDB Compass
and there I hit this little refresh icon.
And we see that we now have a collection users.
When I click on that,
we also see the new entry that was added.
So the email address is john@acme.com.
It has the object ID.
That is the unique ID automatically created by MongoDB.
It has this createdAt and updatedAt
that we get because I set this timestamp property to true.
And we also see this password
but this password is clearly not what I entered before.
This is what preceive hook that we saw before does.
So it took this plaintext password
and passed it to some hashing function
and created a hash that is now stored to the database.
So why did I make this effort?
I did this because it's very bad practice
to store passwords in plaintext
because if your data gets compromised,
the intruder will gain access to all passwords as well.
This happens more often than you think
and the real problem is that users tend
to use the same password everywhere.
So this does not only compromise now your page
but the intruder has their email address
and the password and they will try
to use this combination on other sites as well.
So this hash that you see here
is the product of a hashing function.
But how does this work?
Because of course, you want to log in
with your plaintext password
and somehow, this plaintext password
has to now be converted to this hash
or can we infer the original password from this hash?
But how would this then make sense?
Because then an intruder could do the same.
So there is obviously something missing here
and I explain that to you now.
Let's say we want to store a password,
Mysecretpass to the database,
and preceive hook kicks
and passes now this password to the bcrypt hash function.
Underneath the hood,
bcrypt now calls genSalt
and genSalt also take an argument,
the so-called cost.
So the cost is basically a measure
on how hard it will be to crack this password.
As the default is 10, 12,
it's really, really hard to crack.
The result of genSalt is then some string
and this string consists of the version,
the cost again and then the so-called salt,
which is a random string,
which will then be added to your password
to make it even harder to crack.
Now, all that is combined in the hashing function
and the resulting hash now contains again the version,
the cost, the salt, and then also the resulting hash.
So hash is the product of a hashing function.
And as you cannot reproduce the original potatoes
from your hash browns,
a good hashing function makes it impossible
to calculate the original string from it.
What is guaranteed though
is that the same hashing function
will create the same hash when provided
with the same argument.
We used bcrypt for this hashing
and it's pretty much the gold standard
for password encryption in Node.js
and it uses the Blowfish algorithm in the background.
So let's assume we now have this hash stored
to the database.
How can we now let a user log in
with the plaintext password?
For that, bcrypt gives us the compare function.
This compare function takes, first of all,
this plaintext password.
But it also looks into the stored hash password
and from there, it takes first, diversion,
then the cost
and also this random salt string
and with that, it can run the same hashing function again
that was used when we created the hash in the first place.
And this now, if the password is correct,
will result in the same hash
that we have stored in the database
and if this is the case, then the passwords match
and the compare function will return true.
As you see here, this is a rather complex topic.
If you want to learn more,
just follow the link that I provided here.
This concludes the chapter on MongoDB
and Mongoose and in the next chapter,
we will learn more about key-value stores.