Phase 3: Backend & APIs

Password hashing, bcrypt & secure storage

Intermediate ~3 min read
Think of it this way A friendly analogy. Read this if the technical version feels dense. Show Hide

Imagine you have a super-secret recipe for your absolute favorite cookies, and you want to keep it safe from anyone who might try to sneak a peek. If you just wrote the recipe down on a piece of paper and left it lying around, anyone could read it and make your cookies, or even pretend they made them! That’s exactly why we never store passwords plainly on computers. If someone managed to get into the computer's storage, all your secrets would be out!

Instead of writing down the actual recipe, imagine you put all the ingredients for your cookie recipe into a special, one-way blender. This blender mixes everything up into a unique, mushy paste that looks nothing like the original ingredients. This paste is like a "password hash." The most important thing is that once it’s a paste, you absolutely cannot un-blend it back into separate eggs, flour, and sugar. It’s a one-way street! So, even if someone found your secret paste, they wouldn’t know the original ingredients or steps to make your cookies.

Now, some of these special blenders are super-duper fast. If a speedy blender just makes a paste, a sneaky person could try blending millions of different ingredient combinations very quickly until they found one that matched your paste. That’s still not safe enough for passwords! So, we use a very special kind of blender, like bcrypt, which is designed to be super slow. It takes a long, long time to make that paste, even if you know the ingredients. And here’s another clever trick: for every single recipe, we add a unique, random "mystery spice" (we call this a "salt") before blending. So, even if two people have the exact same cookie recipe, because their mystery spices are different, their pastes will look totally unique!

This means when you try to log into a website, you type your password, but the computer doesn't check your password directly. Instead, it adds its unique mystery spice to the password you typed, puts it through the super slow blender, and then checks if the resulting paste matches the special paste it has saved for you. If they match, great! You’re in! This way, even if a bad guy finds the stored pastes, they’re just left with a bunch of unreadable, slow-blended goo and have no idea what your original secret recipe (your password) was. So when you build your own websites or games later, you’ll know exactly how to keep your users' secrets safe.

When dealing with user authentication, the absolute golden rule is: never store passwords in plain text. Imagine a data breach where your database is compromised. If passwords are unhashed, every user's account is immediately vulnerable, not just on your platform but potentially on others if they reuse passwords. Password hashing is a one-way cryptographic function that transforms a plain text password into an unreadable, fixed-length string of characters (the hash). This process is irreversible, meaning you cannot reconstruct the original password from its hash. This way, even if an attacker gains access to your stored hashes, they can't directly log in as your users or discover their actual passwords.

While many hashing algorithms exist, not all are suitable for passwords. Fast algorithms like MD5 or SHA-256 are designed for data integrity checks, not password security, as they can be quickly brute-forced or exploited with rainbow tables. For passwords, we need a slow, adaptive algorithm like bcrypt. Bcrypt incorporates two crucial features: salting and a work factor. A unique, random "salt" is generated and combined with each password before hashing, ensuring that even identical passwords result in different hashes. This protects against rainbow table attacks. The "work factor" deliberately makes the hashing process computationally intensive, slowing down brute-force attempts significantly. As hardware improves, you can increase the work factor, making your system adaptive to future threats.

Once a password is hashed using bcrypt, you store only this generated hash string (which typically includes the salt and work factor) in your database. When a user attempts to log in, you take their provided password, apply the exact same hashing process (using the stored salt and work factor embedded in the hash string), and then compare the newly generated hash with the one stored in your database. If they match, authentication succeeds. You never decrypt or try to reverse the hash. For secure storage beyond the database, ensure your database connection strings and other secrets are managed via environment variables, and that your database server itself is properly secured, limiting access and applying regular security patches.

Key Takeaways

  • Never store plain text passwords; always hash them.
  • Use a strong, deliberately slow, and adaptive hashing algorithm like bcrypt.
  • Ensure each password hash uses a unique, random salt to prevent rainbow table attacks.
  • Store only the password hash (containing the salt and cost factor) in your database.
  • Authenticate by hashing the provided password and comparing the resulting hash to the stored hash.

Code Example

javascript
Preview

How this code works

This code provides the essential functions for securely handling user passwords in an application. Its main job is to transform a plain-text password into an unreadable, irreversible hash for storage, and then to safely check if a user-provided password matches that stored hash. The bcrypt library is imported to perform these cryptographic operations. A crucial element is saltRounds, which defines the "cost factor" for hashing. A higher number like 10 makes the hashing process intentionally slower, which makes it much harder for attackers to guess passwords quickly, improving security at the cost of a tiny bit more processing time.

The hashPassword function takes a user's plain password and uses bcrypt.hash with the specified saltRounds to generate a unique, secure hash. This hash is what gets saved in the database, never the original password. Because hashing is a one-way process, the original password cannot be recovered from the hash. When a user tries to log in, the verifyPassword function comes into play. It takes the password the user just typed and the storedHash from the database. Crucially, bcrypt.compare then securely re-hashes the provided password using the salt and cost factor embedded within the storedHash, and compares this new hash to the storedHash. It returns true if they match, signifying a correct password, or false otherwise, all without ever revealing or processing the original plain password directly.