Secure Password Storage for Web Sites


Any Web site that wants to store and verify passwords securely should use:

(1) The right algorithm, such as bcrypt or PBKDF2. Both algorithms generate (or “derive”) a hash (or “key”) from a password, which is why they’re called “password-based key derivation functions”, or

Both algorithms take these parameters:

  • A password. For information on good passwords, see point 2 below.
  • A salt. The salt is designed to make each hash unique for a given password. Without the salt, an attacker could use a lookup table, or a list of possible passwords and their hashes, and try each password in the list in turn, or if the attacker somehow has access to the database, look for hashes that correspond to passwords in the lookup table and try those passwords.
    A good salt should be unique for each password, since otherwise the same password will be hashed in the same way. A salt can include, for example:

    • A unique value for each password. For instance, if each password corresponds to a single user, then this
      value can be a user ID (such as the primary key in the users table of the database, not to be confused with
      a username)
    • A unique value for the Web site, which is the same for all passwords. For instance this could be the
      site’s name or domain name. This is to help ensure that hashes are different on different
      Web sites, even if some users use the same password on two or more sites, as they tend to do.
    • Optionally, a randomly generated value, 16 bytes or longer, which is the same for all passwords. This is optional because a salt does not have to be random or even secret, but rather to preclude the use of lookup tables to figure out every password in the site.
  • An iteration count. This value is designed to increase the time needed to mount a dictionary attack
    or brute force attack by making the operation require more computational power. This value should be
    set to as high as possible without causing unreasonable delay.

There is also scrypt, which can also be configured to use more memory in addition to more time, but it’s much newer and less studied.

Using a hash function by itself, such as MD5 or an SHA hash function, is less secure since their outputs can be precomputed for commonly used passwords. Using an encryption function such as AES is also not ideal for the same reasons, but also because the output of the encryption function reveals the password’s length, and because the output is reversible once the key is known.

(2) A good password policy that helps ensure that users use secure passwords:

  • Let users enter passwords of any length, but enforce a minimum password length rather than a maximum length, as
    some Web sites tend to have. A good minimum is 15 characters.
  • Allow Unicode characters in passwords. However, it would be reasonable to forbid characters 65534, 65535, and 0-31
    in passwords, since they are difficult to type.
  • Passwords should not consist of a user name, just numbers, or just letters.
  • After a certain number of failed log-in attempts (such as 5), the Web site should intentionally slow down further log-in attempts by a few seconds. This will help make “on-line” dictionary attacks or brute-force attacks less feasible.
  • Some Web sites, such as Yahoo Mail, force users to re-enter their passwords the next time the user visits the site
    after a certain time. This can be a useful strategy to try as well.

Aug. 28: Edited with information courtesy of martinstoeckli.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>