How to Properly Store Passwords: Salting, Hashing, and PBKDF2

Поделиться
HTML-код
  • Опубликовано: 13 окт 2024
  • #PBKDF2 #AND #HASHING #SALTING #PASSWORDS #STORE #PROPERLY #HOW
    How to Properly Store Passwords: Salting, Hashing, and PBKDF2
    Passwords are very private information, and you don’t want to be responsible for a data breach. You should take the highest precautions if you have to handle them in your application, and hash them properly.
    Most of the security problems with passwords occur after an attacker has gained access to your server, and is able to view the database where you store passwords. While it’s definitely a good idea to lock down your server to prevent unauthorized access in the first place, you should still implement damage control for the worst case scenario.
    The best way to deal with passwords is not at all. Unless you have a specific need to handle passwords directly, you can use OAuth to have someone else handle it for you. This is also called third-party sign-on, and you’ve probably encountered it before if you’ve ever been asked to sign in with Google or Facebook.
    OAuth is more complicated than password authentication, but even if you’re compromised completely, there is zero password data for an attacker to see, not even hashes.
    If you have to store passwords, you should never store them in plaintext on your server. “Plaintext” means it’s readable by an attacker with access to your disk. For example, if you simply take a user’s password and store it in your MySQL database, that’s storing in plaintext. This is why you’re always given a link to reset your password instead of the company just telling you what your old password was.
    The solution to the plaintext problem is hashing. A hash is a function that takes a value and generates a unique key. For example, the phrase “password” has a SHA256 hash of:
    So, rather than storing the password on the server, you store this hash. Hashes are different from encryption in that they’re one-way functions. You can hash something, but it’s impossible to “unhash” it without just straight up bruteforcing the hash. This means there’s no secret key to store, and even if an attacker gets their hands on a hash, they’ll have to bruteforce it first to see the contents.
    This plaintext rule applies to auxiliary things like log files as well-if the attacker can read it from anywhere, that’s a major issue. This also applies to plaintext transmission methods like HTTP, though you should never send passwords over the wire anyway. You want to generate a hash on client side when they enter it in, to prevent passwords from being sniffed over the network.
    Even though securing traffic with HTTPS would prevent man-in-the-middle attacks on the client’s side, if an attacker had access to your server, they could decrypt and sniff newly created passwords. This also makes your service more trustworthy, as a user won’t know if you’re secretly storing their password behind the scenes. But if you only see a hash, even the server doesn’t know what their password is.
    If you simply want a good hash to use, choose PBKDF2, as it’s used specifically for storing passwords and is very secure. You’ll probably want to use the JavaScript implementation on the client side, but if you must use it server-side, you’ll want to use an implementation for your language.
    Hashing has a problem, and regular password hashes can be cracked with a method known as rainbow tables.
    To attack a hash, you could simply try every single possible password for each hash entry in your database, which is known as bruteforcing-slow, but not entirely impossible, depending on how weak the password is and the hash used to store it. It may take a few days or weeks of computation time, but an individual weak password could be cracked eventually.
    Rainbow tables speed this up dramatically. Rather than bruteforce each password individually, the hashes for every possible password are computed beforehand and stored in a file. This file can be massive, on the scale of many hundreds of terabytes. All it is is a key-value pair of each possible password (up to a certain size, depending on the table), and the corresponding hash.
    It’s a tradeoff of storage space for time; you only have to perform the hash once, then you can look it up in the table instead (which is much quicker). These tables are publicly available, and easy to generate.
    To prevent this attack vector, you should add a salt-a random string that you append to the end of the password before hashing. Instead of hashing “password“, you would hash:
    This salt is stored alongside the password hash in the database. When a user enters their password, you send the salt back to the user so they can add it to the hash. You can think of it like each user having their own unique rainbow table, which defeats the purpose of them entirely.
    The salt itself isn’t secret. It doesn’t have to be, as all it is doing is preventing rainbow table creation, and you’re storing it in plaintext anyway. Salted passwords can still be bruteforced individ…

Комментарии •