Hello and welcome, I'm James Murphy from mCoding
and today we're talking about storing passwords, and how hashing, salting, and peppering your
passwords can improve your security. Before we get started, if you're interested
in password security, there's a good chance you'd like your own website,
and, if so, check out this video's sponsor Hostinger. Host a website for just $1.39 a month with
the single shared hosting plan. Or for just $2.59 a month, host up to a hundred
websites with the premium shared hosting plan, which comes with a free domain. Use code MCODING at checkout for up to 91%
off, claim your free domain, and don't forget to
secure it with https. All right, let's talk about database leaks. Whether it be from a SQL injection attack,
a misconfigured server, or a disgruntled employee, database leaks are bound to happen from time
to time. Not necessarily to your company, but to some
companies. So let's go through a hypothetical database
leak and see what happens if plaintext passwords leaked,
versus hashed passwords, versus salted hashed passwords, versus peppered salted hashed passwords. Each of these things provides a different,
extra, level of security that the previous did not. All right, let's get started with plaintext
passwords. It's the simplest case and it provides the
least security for obvious reasons. Updating a password in plaintext just involves
taking the password from the user, storing it in some kind of user object and
then sending that to the database to, you know, update the record. Verifying it is just comparing the inputted
password against the stored one in the database and
one thing you can do is to use a compare digest, which is a constant time compare, to avoid
things like timing attacks. Although if you're storing passwords at all
you've already messed up. In main here I've just got a dummy database
class that prints things out about the user when you call the store method. Our users are just going to be a dataclass
with an email and a password, and I'll simulate updating the password for
a user and then verifying the correct and an incorrect password. In the event of a database leak, this is obviously
the worst case. The hacker gets every user's email and password
in plaintext. That means that they can use that email and
password to login as any user for this service, or they can try using those credentials to
log into other services. So if a hacker gets your Facebook password,
they may just try to log into your bank account with that same information. Of course, you're supposed to use a unique
strong password for every service that you use, but who actually does that? Let's see how we can improve the situation
by incorporating a hash function. In this version, we take in a hash function
and, instead of storing the raw password, we store the hashed version of the password. We additionally store the name of the hash
function that we used so that in the future, if we ever want to migrate to a different
hash function, we can tell which function was used to hash the password. Verifying the password then just comes down
to looking up the hash function that we used, and then hashing the password with the given
hash function and comparing against the one we have stored. It's also important to note here that for
all these examples I'm actually doing some basic 64 encoding. This is very common in practice and it makes
it a lot easier to read when we print things out. It's not super important,
but I do also want to note that the dollar sign is not used in base 64 encoding. That makes it safe to use as a separator for
the name and hash, and that's why we can just split the password
like this to recover those things. Okay so let's get to taking a look at what
the hacker sees when a database of hashed passwords is leaked. So here's what the hacker would see if hashed
passwords were leaked. They can't see the passwords directly, so
they do have to do at least some work, but they can recognize and break common passwords
because these hashes could be precomputed. They can also guess passwords offline for
those that aren't precomputed since they know which hash function was used. This is a big win since the server won't ban
them for too many wrong attempts, potentially allowing them to break weak passwords,
even if they haven't been precomputed. Also if they are able to crack a password
that multiple users have used, they crack the password for everyone that
used that password all at once. They can also see if any two people have the
same password since those two passwords would have the same hash,
even if the hacker isn't able to identify what the password is from this data. This is a lot better situation than plaintext
passwords being leaked, but, at this point, you should probably assume
that any one of your users that had a weak password is compromised. So how can we improve this by using salts? Well what is a salt anyway? A salt is just a little bit of extra randomness
that we sprinkle in with a user's password. A salt should be unique for each user. You can see here that, instead of just hashing
the password directly, we hash the salt together with the password. Then, when we store the password, we actually
stored the name, the salt, and the hashed password. When we verify, we recover the salt from the
user's stored password and then use that together with the inputted password,
hash it, and use that to compare against the hashed password that was stored for the user. So here's what the hacker sees when salted
hashed passwords are leaked. Of course, they can identify the hashing algorithm
that's used and, because we put the salt in there,
they also get the salt out. Of course, then there's the hash. But, if the salt is right there, what's the
purpose of using it? The hacker just gets it for free... Well the big win here is that hackers can
no longer recognize hashes of weak passwords because throwing those salts in there made
them all unique. Precomputed hashes become effectively worthless. A hacker can still guess passwords offline
and check to see if they're correct since the salt is known,
that was part of the information that was leaked in the database. This allows them to potentially break weak
passwords. But if the hacker does spend the time to crack
a weak password, it only cracks it for that one person. It doesn't crack it for everyone that shared
the same password. They also can no longer tell if two people
have the same password by looking at the hash. Okay then, what's a pepper and how does it
differ from a salt? Well, a pepper is similar to a salt in that
it's some randomness that you sprinkle in with the password,
but its primary difference is that a pepper is specifically something that you do not
store in the database. A salt was stored in the database with the
password, but a pepper is stored somewhere else. It's stored, perhaps, in your application
code, or in a secure memory enclave. Because it's not stored in the database, it's
something that a hacker doesn't see even if the database is leaked. Additionally, it's typical to only have one
pepper for your entire application. Since we can't store the pepper in the database,
it wouldn't make sense to have one for each user because where would we store that information? The way that you use a pepper, though, is
pretty similar to the way that you use a salt. You just sprinkle it in with the salt and
the password at hash time, and then when you want to look it up,
you still get the salt from the hashed password that was stored in the database,
but you get the pepper from wherever you get it, stored in some secure memory enclave. So what does using a pepper in addition to
the salt and hashing buy us? Well, the hacker can still see the hash function
and salt, but the pepper isn't there because it wasn't stored in the database. The hacker doesn't even know a pepper is involved. And because the hacker doesn't know the pepper,
they can no longer guess weak password offline. The hacker would need to simultaneously leak
the database and the application code to get any useful information out of the database
leak, at which point it would be similar to the
situation where we were just using hashed and salted passwords. The only downside to using a pepper is that,
since no database is used, it may be harder to ensure that every server
has access to this pepper. Because of these benefits, I think the peppers
are going to start picking up a lot more steam in the future. But, currently most libraries don't support
peppers, but they do support salts. I'd like to see that start to change in the
future, but right now that's just how it is. Because you really shouldn't be writing your
own authentication systems, you should just be using open-source well-proven
ones, this probably means that you won't be able to use peppers in the near future because
they don't support it yet. But I will at least link to a best-practices
document so that you can at least see what you should be doing in the modern day
and how you should be storing passwords securely using the tools and projects and libraries
that are available to us right now. So that's all I've got on hashing, salting,
and peppering your passwords, I hope you learned a little bit. If you enjoyed the video, please don't forget
to subscribe, leave a like, leave a comment, it really helps out with the algorithm. See you next time.
Good stuff. Made it really easy to understand both how to implement these techniques, and why they should be used.
I also rather liked the use of
hmac.compare_digest
, not just because it's the right tool for the job, but also because it's a subtle reminder that cyber security is easy to mess up for everyone who would've used==
there (: