Password encoding with BCrypt

Spring Security · lesson 5 of 31 · 3 min read

Store passwords the only acceptable way and understand what BCrypt is doing for you.

Open this lesson in the learning hub

Key points

  • Never store a raw password. Store a hash. One PasswordEncoder bean and Spring Security uses it everywhere.
  • BCryptPasswordEncoder is the safe default. It salts every hash, so two identical passwords look completely different.
  • Default strength is 10; each +1 doubles the work. 10-12 is normal — measure login latency before raising it.
  • The {bcrypt} prefix comes from DelegatingPasswordEncoder — switch algorithms later without a mass reset.
  • matches() re-hashes the input with the stored salt. There is no decrypt, and that is exactly the point.
  • BCrypt only hashes the first 72 bytes. Reject absurdly long inputs rather than silently truncating them.

Example

@Bean
PasswordEncoder passwordEncoder() {
    // encodes as {bcrypt}$2a$10$... and can still verify legacy formats
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

// Sign-up: hash once, store the hash
String hash = passwordEncoder.encode(form.password());
users.save(new AppUser(form.email(), hash, Set.of("ROLE_USER")));

// Login: Spring Security does this for you
boolean ok = passwordEncoder.matches(form.password(), hash);

Hash with BCrypt, never decrypt, and let DelegatingPasswordEncoder future-proof you.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Security course, and every lesson in it is listed on the Spring Security contents page.