Hashing vs. Encryption: How Your Password Is Being Stored in Server

Let’s say you set up an account at VerySecureWebsite.com. You type in your email address and password and set up your account. A little while later you receive an email informing you that, ironically, the website has been hacked, and the usernames and passwords of every user, which were stored in plaintext, are now for sale on the dark web. While you start changing the password on all your accounts (you only use one, you monster), you wonder, “Isn’t that a bad idea? Shouldn’t my password be in some kind of secret code so hackers can’t just read it?

You’re correct. Any web app or service that uses a username/password login system should be storing their users’ passwords using a salted hash, possibly even a salted slow hash, perhaps with a pepper. If this is starting to sound more like breakfast than cryptography, don’t worry: unlike your password (hopefully), secure password storage isn’t too difficult of a topic to crack.

Plaintext and basic encryption


UsernameEntered PasswordStored form

Storing plaintext passwords in an Internet-connected database is a pretty bad idea: if the database gets hacked, anyone who has reused one of those passwords is now at risk. And yet a disturbing number of websites still do it, probably because security upgrades are more for the customer than the company. If you want to test whether a site is doing this, try selecting the “forgot password” option. If they just send you your password instead of a reset link, it’s being stored in plaintext.

UsernameEntered PasswordEncrypted with AES-128 Key: WeakKey

Encryption may sound like a strong way to store passwords, but it’s really just a step above plaintext. An encrypted password can generally be decoded with a key, and if the hackers can find or guess it, the encryption is useless.

Hashing > encryption


UsernameEntered PasswordString to be hashedHashed with SHA-256

A hash function is basically just one-way encryption: you convert the plaintext password to a secret code, but there’s no key to convert it back, meaning you can never derive the actual password from the hashed version.

This is how most secure websites manage their passwords:

  1. The user creates an account
  2. The user’s password is run through the hash function and stored in the database
  3. Every time the user logs in, the database hashes the password they entered and checks to see if the entered hash matches the hash they have on file.
  4. If yes, the user can log in

With a hash, the app/site never stores your actual password anywhere, and a hacker who breaks in will only get a list of letters and numbers that can’t be decoded. Depending on how strong the algorithm is, these hashes can be pretty difficult to crack.

Hashes aren’t hackproof, though. All an attacker has to do is run a dictionary of potential passwords through the hash function, then compare those hashes to the hashes in the database. When two hashes match, the hacker can just look at which password generated that hash.

To save time and computing power, many attackers just use a lookup table (or a “rainbow table,” a space-saving version of lookup tables), a pre-generated table full of potential passwords and their hashes. You can actually try hashing a plaintext word and then use a lookup table on the hash yourself; it’s not too hard. Essentially, if your password is at all common, the hash of that password is probably already in a lookup table. This is a great reason not to use common passwords.

Salted hashes > hashes


UsernameEntered PasswordString to be hashedHashed with SHA-256,
salt = XcyKn42, prepended

Unlike slugs, salt makes hashes stronger. Since the entire hash changes even if just one letter of the plaintext word is changed, all a site needs to do to foil lookup tables is add some extra plaintext to the password before it’s hashed. The attacker will be able to read the plaintext salt since it’s stored in the database, but it forces them to recompute every possible combination of potential passwords and salts.

Of course, salted hashes can still be cracked. Hackers can just add the salt to the password they’re guessing, hash the combination, and wait for matches to pop up – a standard dictionary attack. Since modern GPUs can make billions of guesses per second, this isn’t at all infeasible, but it does make the process a lot more annoying. Failing that, brute-force attacks are slow but very effective.

Making hashes even stronger: other tactics


UsernameEntered PasswordString to be hashedHashed with Bcrypt,
salt = XcyKn42, prepended,
12 rounds

Slow hashing algorithms, like PBKDF2 or bcrypt, use a technique known as “key stretching” to slow down dictionary and brute force attacks. This essentially involves setting the hash function to iterate a certain number of times (though it’s a bit more complex than just running the same thing over and over again), so that in order to reach the correct hash you have to use a lot of computing power. If a site is doing all this, their security is pretty good.

UsernameEntered PasswordString to be hashedHashed with Bcrypt,
salt = XcyKn42, prepended,
12 rounds,
pepper = |4|\/|@p3pp3r, appended

For added security, you can also “pepper” your hashes – which hopefully are already salted. A pepper, like a salt, is a set of values attached to the password before it is hashed. Unlike a salt, however, there is only one pepper value, and it is kept secret, separate from the salts and hashes. It adds another layer of security to the salted hash, but if the attacker manages to find it, it’s no longer very useful since the attacker can just use it to compute new lookup tables.

Don’t make a hash of your hash

Password security has made some big advances – and so has the art of cracking that security. Unfortunately, humans are still bad at password management, and databases don’t upgrade security as often as they should. In general, assume that whenever you create an account, the password is being stored with relatively weak security. If your password is common or a dictionary word, then it’s at a pretty high risk of being cracked. Make your passwords long, mixing letters, numbers, and symbols, and you’ll be helping hash functions do their best work.

Image credits: Hash function


  1. “Storing plaintext passwords in an Internet-connected database is a pretty bad idea: ”
    Then there is this:

    ” Exclusive: Facebook stored hundreds of millions of user passwords in plain text for years https://t.co/1iklirG5Hu pic.twitter.com/cmbpYmTrng

    — briankrebs (@briankrebs) March 21, 2019″

  2. I just saw that news today! Weirdly good timing for my article, honestly. Seriously, though; it’s more something you expect from a fan club site than from one of the biggest companies in the world. Hashing passwords is sort of data security 101 at this point.

    1. It may be data security 101 at most companies but, based on the revelations of the past couple of years, FB seems to have thrown out the textbook. FB is like the 800lbs gorilla that does whatever it wants.

  3. How about using a PW Manager to generate your pw’s which becomes the “plain text” gobbledigook pw on the web site?

    1. Great question! That will definitely do good things for your password security since a long, randomly-generated, non-dictionary password is very unlikely to be in any lookup tables and would require more work for a brute-force hash attack. The easiest way to crack hashes is using a wordlist, and if your password doesn’t get any hits in the wordlist there’s a good chance the attackers will just skip it, unless they’re specifically trying to get into your account.

Leave a Comment
