跪拜 Guibai
← All articles
Java · Spring

BCrypt vs Argon2 in Spring Security: When Memory Hardness Matters

By 都叫我大帅哥 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

BCrypt's low memory footprint leaves it vulnerable to GPU-accelerated brute force at scale, a gap that Argon2 closes by design. Teams building new Spring Boot services get a stronger default by reaching for Argon2PasswordEncoder, while those on BCrypt can stay put without immediate risk.

Summary

BCryptPasswordEncoder has been the go-to password hasher in Spring Security for years — it's mature, predictable, and requires no extra dependencies. Its single strength parameter controls CPU cost by doubling Blowfish rounds, and a 16-byte random salt is embedded directly in the 60-character output. The catch: BCrypt uses almost no memory, so attackers can still parallelize guesses across thousands of GPU cores.

Argon2PasswordEncoder, winner of the 2015 Password Hashing Competition, adds explicit memory hardness. By forcing every hash attempt to allocate a configurable amount of RAM (default 4 MB), it makes GPU and ASIC attacks economically infeasible. Spring Security ships Argon2id support since Boot 2.7, though it pulls in Bouncy Castle. The trade-off is more knobs to tune — salt length, hash length, parallelism, memory, and iterations — versus BCrypt's single strength dial.

For new projects with compliance or high-security requirements, Argon2 is the stronger choice. Existing BCrypt deployments don't need a panic migration; the algorithm remains unbroken in practice. A DelegatingPasswordEncoder lets teams support both formats during a gradual transition.

Takeaways
BCrypt automatically generates a 16-byte random salt and embeds it in the hash output; no separate salt storage is needed.
The strength parameter sets 2^strength Blowfish rounds — default 10 (1,024 rounds), and each +1 doubles the work.
BCrypt truncates passwords longer than 72 bytes, so long passphrases need pre-hashing or an alternative encoder.
Argon2id is the recommended Argon2 variant in Spring Security, combining GPU resistance and side-channel protection.
Argon2's memory parameter defaults to 4 MB (1<<12 KB), making GPU parallel cracking impractical because each guess must allocate that memory.
Argon2 exposes five constructor parameters: saltLength (16), hashLength (32), parallelism (1), memory (4 MB), and iterations (3).
Spring Boot 2.7+ bundles Argon2PasswordEncoder via spring-security-crypto 5.x, but it requires the Bouncy Castle dependency.
DelegatingPasswordEncoder allows multiple hash formats to coexist, enabling a gradual migration from BCrypt to Argon2 without resetting all passwords at once.
BCrypt strength upgrades only take effect on the next login; existing hashes cannot be re-encoded in place.
Pbkdf2PasswordEncoder and SCryptPasswordEncoder are alternatives — SCrypt also offers memory hardness, while PBKDF2 is mainly for legacy compatibility.
Conclusions

BCrypt's single strength knob is both its greatest usability feature and its architectural ceiling: you can only dial CPU cost, not memory cost, which leaves a vector open that modern hardware exploits.

The 72-byte password truncation in BCrypt is a real footgun for apps that accept passphrases; developers often don't discover it until a security review.

Argon2's five-parameter constructor offers precision but also invites misconfiguration — setting parallelism too high on a multi-tenant server can degrade performance for all users.

Spring Security's decision to bundle Argon2 support without making it the default reflects a pragmatic bet: BCrypt is good enough for most, and Argon2 is there for teams that know they need it.

The recommendation to keep a single hash verification under one second is a useful rule of thumb that applies to both algorithms and prevents login-time DoS.

Memory hardness is not a theoretical nicety — cloud GPU instances are cheap enough that BCrypt's lack of memory cost is a measurable weakness for high-value targets.

Concepts & terms
Memory hardness
A property of a password hashing function that requires a significant amount of RAM to compute each hash, making parallel attacks on GPUs or ASICs impractical because those devices have limited memory per processing unit.
Adaptive hashing
A hashing scheme whose computational cost can be increased over time by tuning parameters (rounds, memory, parallelism), so it stays resistant as hardware gets faster.
DelegatingPasswordEncoder
A Spring Security password encoder that prefixes stored hashes with an algorithm identifier (e.g., {bcrypt}, {argon2}) and delegates to the matching encoder, allowing multiple hash formats to coexist during migrations.
Side-channel attack
An attack that extracts secrets by measuring physical side effects of computation — timing, power draw, cache access patterns — rather than breaking the algorithm mathematically. Argon2's data-dependent memory access pattern makes such attacks harder.
Rainbow table attack
A precomputed lookup table mapping plaintext passwords to their hash values, used to reverse hashes quickly. Unique random salts defeat rainbow tables because each password would need its own table.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗