Hello and welcome to this fundamentals of cryptography course, in this section of the course, we've
been talking about hash functions and so far we've been focused on the theoretical and security aspects
of them, looking at what they are, how they work, what their security assumptions are, and how different
hash functions that we know of have been broken for this video.
In the next, we're going to look at some of the practical applications of hash functions, namely how
they're used in the real world.
And our first application we'll look at is for password security.
So in this video, we have three main sections.
We're going to start out by talking about the need for secure credential storage.
Essentially why we ever need to store credentials.
Then we'll talk about a history of password management.
So password management has sort of been a back and forth game between defenders and attackers.
Some new security feature will be invented, defeated by the attackers.
And so then something else needs to be added.
And then thirdly, we'll look at some of the challenges and secure password storage.
So some of the common mistakes that companies have made when storing the passwords of their customers
and users.
And so why do we need to store credentials securely?
So passwords are the most common method for authenticating users to a service.
There are been several attempts to, quote unquote, kill the password.
However, they've never been successful so far.
Passwords are here to stay until someone comes up with a better idea that can actually achieve user
adoption.
And so how passwords work is that a user provides a password and a server service compares it to their
stored version.
And if they match, then the users granted access.
If they don't match, access is denied under the hood, you might have a bit more complexity determining
number of password attempts, et cetera.
Balancing between someone mistyping their password versus protecting against a brute force password
guessing attack.
But in general, that's how it works.
And so an important consideration in this is the fact that that service needs a secure method for storing
the authentication information or the password that they are going to use to compare to the one provided
by the user.
If an attacker can gain access to their complete database of passwords, then all of their user accounts
could be compromised.
And so historically, there's been multiple different iterations of passwords.
Storage at the very beginning would be plain text, passwords, storage.
You just store the passwords in a file without any protection.
However, this is very easy to break.
And the reason why is that anyone with access to the file could read the passwords.
And so we need a way to ensure that the passwords maintain some level of confidentiality while still
being able to verify them.
And this is where hash functions come in.
So the next iteration, past hash or pass plaintext is storing password hashes.
And so this works very similar to storing plain text passwords just instead of taking your user password
and comparing it to a password stored on the system.
The system will take that user password, hash it and compare the hash with the one that they have stored.
And so, as we talked about, hash functions are deterministic, meaning that every time that you provide
the same input to the hash function, you're going to get the same output.
And so comparison of password hashes works just as well as comparing the passwords themselves up to
a point.
We've talked about collision resistance as well, where there's an infinite number of inputs that produce
the same password output or paper or hash output.
And so with passwords, anyone who can find a password that collides with your password on the hash
function can authenticate to the service.
So we also need the collision resistance of hash functions to protect against that sort of attack.
And so hash functions are a good fit for secure credential management.
However, on their own, they're not good enough.
And the reason why is rainbow tables, which take advantage of that same determinism that is so essential
for hash functions.
So a rainbow table is a collection of inputs that map to a given output or map to different hash output.
So for each possible output of a hash function, you store a corresponding input.
And so obviously, it's impossible to store all of them.
However, an attacker could create a fairly good sized lookup table.
Maybe the most common passwords and the hash that they produce.
And then if they can steal the hash file or the list of password hashes for the user accounts, they
can very quickly compare.
OK, this hash in this file maps to this password.
No need to actually run the hash operation.
Additionally, with deterministic hashes, you have the problem that the same passwords produce the
same hashes.
And so, as you may know, password security, password reuse use is a big problem.
A disturbing percentage of the population use it the same top 25 passwords, most common passwords.
And so simply by knowing the hashes of those twenty five passwords, there's a good chance that an attacker
could very easily break into a bunch of user accounts.
If we only use password hashes for storage.
And so the next iteration of password management is the storage of salted password hashes.
And so a salt is simply a random, unique value that you append to the password before hashing it.
And this salt is stored in plain text next to the hash.
The salt itself isn't secret.
Its entire purpose is to defeat rainbow tables because with a rainbow table with no salt.
Every password is hashed in the same way.
And so the same passwords produce the same hashes with assault.
If two users have different salts, then their hashes are completely different, even if they had the
same password.
And so this makes it much more difficult for an attacker to identify a user's password from a list of
hashes because they actually have to go through the process of trying a password with the corresponding
salt to get the correct hash, rather than just saying this password produces this hash.
So users Alice, Bob and Charlie all have that hash.
That means that this is their password.
However, again, salting password hashes isn't quite enough.
And the reason why is that computers are getting better and better and so performing only a single hash
operation takes some computational work.
But there's only so much.
And so if an attacker has a list of common passwords to try, they can rip through that list pretty
quickly with a single hash function application while they're not searching the entire space of potential
passwords to find which one it is.
They're searching this much more manageable list of probable passwords.
And so we also not only need to defend against stolen password files, rainbow tables, et cetera,
we also need to defend against the probability that people use bad passwords.
And so now the current iteration of password management is storing salted password hashes that are generated
using key derivation functions.
And so a key derivation function is a fancy phrase for running a hash algorithm.
A lot of times, one after another.
So, for example, instead of just taking your password, hashing it and comparing it, a computer will
take your password, hash it, take the output of that, hash it and repeat that process.
So many times, maybe 100 iterations in the whole purpose of this is to make it take longer to go from
a password to the final hash.
That can be tested.
And so under normal operation, you know, your password or you probably can get it within a few guesses.
And so maybe a legitimate user will only have to go through this process, say, at most five times.
And in most cases, just once.
And so a little bit of extra overhead.
Not a big deal.
If you're an attacker trying a list of hundreds or thousands or tens of thousands of possible passwords,
this additional safe five seconds or 10 seconds to try a password adds up really quickly.
And so this helps to protect against brute force, password guessing because the cost of testing massive
list of passwords against a user account to figure out if it's a weak password is much, much higher
than if you're using a single iteration of a hash function.
And so this is the history of Password's storage and management and nutshell, you can go from plain
text password storage that's vulnerable to everything through hashes, through salting, to Katie apps
which protect against even the use of weak passwords.
However, a lot of organizations have had troubles making it through that entire process or history.
Even in recent years, companies have still been discovered through data breaches to have poor password
storage practices, for example.
Not that long ago, Facebook had a data breach where they discovered that due to debugging information
in some applications, it was possible for user credentials to be stored in plain text on their server.
And so if someone knew this and went looking through these files on the server, they could get people's
Facebook passwords, which is a problem.
And so this violates password storage because you're not even using a hash function to protect it.
Anyone who looks at the file can steal someone's password.
Another example of a common mistake is the use of an insecure hash function.
So in the previous video, we talked about some of the more common hash functions and how, say, MDG
five and SHA one are insecure.
Now, while SHA 256 is secure and the difference between them is that it's been demonstrated to be possible
to find a collision in SHA 250 or an M.D. five in SHA one.
While we haven't managed to do that yet with SHA 256.
And so in the case of my heritage, when they had a data breach, it was discovered that they were using
SHA one for password hashing, despite the fact that SHA one has been considered untrusted since about
2015.
And so another example of making a mistake by simply using the wrong hash function for security.
And then a third example of a common mistake is improperly applying passwords, salting.
So in order to be effective, a salt has to be unique for every user in the database of users.
So every password has to be individually salted so that you can guarantee that to users with the same
password have different hashes.
In the case of my fitness pal, they use the same hash or same salt for their entire database, which
would protect against a rainbow table unless an attacker had a rainbow table for that particular salt.
But it provided no protection against someone looking at the password hashes and matching up ones that
were the same.
And even that sort of analysis can be extremely useful for password guessing, because if you take all
of those hashes and sort them by frequency, the ones that are most common are the ones that are most
likely to be mapped.
Insecure passwords are most likely to be one of the top 25 passwords, and they might even be organized
by the ranking of the top 25 most common passwords.
And so you could reach the point where for a user account, you need to make one guess and you've already
determined what their password is.
And also the password of every other account that uses that same password.
And so these are three examples and recent examples of companies failing to properly protect passwords
by making fundamental mistakes and credential storage.
And so just as a recap introduced this topic to discuss how hash functions can be applied for secure
credential storage, we need secure credential storage because for password based systems to work,
the server has to store passwords to compare to what the user provides, and they need to do so securely.
We then look through the history of password management and how different types of attacks against one
iteration of the history of passwords storage forced the next innovation.
So using hashes or using salting, using kadee apps, et cetera.
And then finally, briefly discussed a few case studies of failures and password storage where the use
of no hash function or the wrong hash function or misuse of salting could potentially leave a user password
vulnerable to compromise.
So this concludes this video.
And thank you very much.