Dev Learning Lab

The labs on this site need JavaScript to run. The same content is written out below.

Learn › Security › Authentication

Password hashing

How well do passwords hold up when the database leaks?

Two members happen to use the same password (password123). How the passwords are stored in the database greatly changes how long an attacker needs to recover the original passwords after the database leaks. A hash is a value computed from the original in a way that cannot be reversed. This lab compares plain text, a hash, a salted hash, and a deliberately slow hash (bcrypt).

Partly checked against real execution · SHA-256 was actually computed; bcrypt could not be measured

Concepts in this lab

Hash function and salt
A hash function turns an input into a fixed-length value, and the original input cannot be recovered from the result. For passwords, the hash value is stored instead of the plain text, so the plain text is not exposed even if the data leaks. A salt is a random value that is added to each password and is different for each one. It makes the same password produce a different hash, which blocks attacks that use precomputed lists of hashes.
bcrypt
A hash function designed for storing passwords. It generates a salt automatically and includes it in the result, and it lets you set a work factor (cost) that makes the computation slow on purpose. A slow computation greatly increases the time an attacker needs to try a huge number of candidates. Spring Security's BCryptPasswordEncoder uses it.
Symmetric-key cryptography and public-key cryptography
Symmetric-key cryptography uses the same key to encrypt and to decrypt. It is fast, but it has the problem that the key must be shared safely with the other party (AES). Public-key cryptography uses a pair of keys, a public key and a private key. Data encrypted with the public key can be decrypted only with the private key, so there is no key-sharing problem, but it is slow (RSA). In practice, public-key cryptography is used to exchange a symmetric key safely, and then the symmetric key encrypts the data.

Try these

Running with the default settings

  1. Alice and Bob sign up, and both choose password123 as their password. The server stores it in the database using the SHA-256 method.
  2. The stored values of the two members are exactly the same. Anyone who sees the database can tell at once that the two passwords are the same, and recovering one gives the passwords of every member with the same value.
  3. Incident: an attacker has copied the whole member table out of the database.
  4. A hash cannot be computed backward, but tables of precomputed hashes of common passwords already exist. The attacker only has to look the stored value up in a table, because the SHA-256 of password123 is the same value for everyone.
  5. Time needed to try 100 million common passwords against one member: under 1 second. A common password such as password123 is found almost instantly.

Result of this run

Code

MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(rawPassword.getBytes(UTF_8));
member.setPassword(HexFormat.of().formatHex(hash));

Assumptions of this model

The SHA-256 values are actually computed. The bcrypt stored values are example strings that show the format. The guessing speeds show rough orders of magnitude. They assume that, for one high-performance graphics card, SHA-256 makes tens of billions of attempts per second and bcrypt with cost 10 makes a few thousand per second, and they are values chosen to match the orders of magnitude of published benchmarks. The login verification times are also rough values that vary with the server CPU. The default cost of Spring Security's BCryptPasswordEncoder is 10. On the PC used to write this lab, the SHA-256 speed measured with openssl was about 32 million per second on one CPU core (the tens of billions per second on screen is a published figure for a graphics card). bcrypt was not actually measured because the PC has no library for it.

Previous lab: Cookies · Next lab: JWT structure and verification

Concepts in this lab

What this lab shows

Settings

Code


      
    

Diagram

Run comparison

Try these