DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Memory Is a Distributed Systems Problem: Designing Conversational AI That Stays Coherent at Scale
  • The Importance of AI System Memory
  • Java and Low Latency
  • Event-Driven Order Processing Program

Trending

  • Build a GitHub Slack Bot With AWS Bedrock and MCP, Part 2
  • Why DDoS Protection Is an Architectural Decision for Developers
  • Implementing Secure API Gateways for Microservices Architecture
  • Pragmatica Aether: Let Java Be Java
  1. DZone
  2. Coding
  3. Java
  4. My Learning About Password Hashing After Moving Beyond Bcrypt

My Learning About Password Hashing After Moving Beyond Bcrypt

I started with bcrypt because it was easy and widely recommended, but I moved to Argon2 once I understood how modern attacks work.

By 
Dhiraj Ray user avatar
Dhiraj Ray
·
Feb. 16, 26 · Tutorial
Likes (0)
Comment
Save
Tweet
Share
2.1K Views

Join the DZone community and get the full member experience.

Join For Free

For a long time, I thought I had password hashing figured out.

Like many Java developers, I relied on bcrypt, mostly because it’s the default choice in Spring Security. It was easy to use, widely recommended, and treated in tutorials as "the secure option." I plugged it in, shipped features, and moved on.

But after years of building backend systems, maintaining cryptography tools, and answering developer questions, I realized that password hashing is one of the most misunderstood areas of application security — even among experienced engineers.

This article shares what I learned while implementing bcrypt, scrypt, and Argon2 in real systems, why my thinking changed over time, and how modern threat models forced that change.

My Starting Point: bcrypt in Spring Security

If you've used Spring Security, bcrypt feels almost too simple:

Java
 
PasswordEncoder encoder = new BCryptPasswordEncoder();

String hash = encoder.encode(password);


No memory configuration. No tuning beyond a cost factor. It just works.

Bcrypt was a massive improvement over older approaches like SHA-1 or MD5. It's slow, adaptive, and intentionally expensive. For many years, it was absolutely the right answer.

But as I reviewed real-world implementations and saw how developers actually used it, two issues kept appearing:

  • Cost factors set far too low
  • An assumption that bcrypt is resistant to modern hardware attacks

That second assumption is where things start to break down.

How GPUs Changed the Game

Most modern password cracking does not happen on CPUs. It happens on GPUs and ASICs.

bcrypt is CPU-hard, but it is not strongly memory-hard. That means attackers can still scale attacks efficiently using specialized hardware.

This isn't a flaw in bcrypt — it's a limitation of the era it was designed in.

Understanding this was the turning point for me. It explained why newer algorithms exist and why the conversation shifted from "slow hashing" to memory-hard hashing.

Scrypt: My First Step Beyond bcrypt

Scrypt was one of the first mainstream attempts to address this problem by introducing memory hardness.

Instead of just slowing down computation, scrypt forces attackers to allocate large amounts of memory, making GPU and ASIC attacks far more expensive.

When I started working with scrypt, one thing became immediately clear:

Scrypt is powerful, but very easy to misuse.

Its parameters (N, r, p) give you fine-grained control over CPU and memory usage — but that flexibility comes at a cost:

  • Too little memory -> weak protection
  • Too much memory -> application instability or crashes

scrypt solved an important problem, but it also raised the bar for correct configuration.

Discovering Argon2

I first encountered Argon2 while reading modern security recommendations and RFC discussions. It had won the Password Hashing Competition (PHC), which immediately caught my attention.

What stood out wasn't just that Argon2 was newer — it was that it was clearly designed with modern attack models in mind.

Argon2 makes key security decisions explicit:

  • Memory cost
  • Time cost
  • Parallelism

Instead of hiding complexity, it forces you to acknowledge it and it is already demonstrated beautifully here in this tool.

More importantly, Argon2 was designed from day one to resist both GPU and ASIC attacks. That design clarity is why many modern security teams now recommend Argon2id as the default choice for new applications.

A Practical Comparison

From an implementation perspective, here’s how I now think about these algorithms:

  • bcrypt
    Simple, battle-tested, widely supported. Still safe when configured correctly, but limited against modern hardware attacks.
  • scrypt
    Introduced memory hardness early, but easy to misconfigure. Best used when you fully understand its parameters.
  • Argon2
    Explicit, modern, and designed for today's threat models. Slightly more complex, but far more future-proof.

None of these algorithms are "bad." The real risk lies in using them without understanding what they protect against — and what they don't.

When I Would Use Each Today

Based on real-world experience:

  • I would choose Argon2 for new applications where I control the environment and want long-term security.
  • I would stick with bcrypt in mature systems where stability and compatibility matter more than cutting-edge resistance.
  • I would consider scrypt only when Argon2 isn't available and I’m confident in parameter tuning.

Just as important is knowing when not to use each option — especially in environments with limited memory or poor library support.

Conclusion

I started with bcrypt because it was easy and widely recommended. I moved toward Argon2 after understanding how modern attacks actually work.

That progression mirrors the broader shift in the industry.

The best password hashing algorithm isn’t the trendiest one — it's the one you understand, configure correctly, and can maintain over time.

Password cracking Spring Security Memory (storage engine) systems

Published at DZone with permission of Dhiraj Ray. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Memory Is a Distributed Systems Problem: Designing Conversational AI That Stays Coherent at Scale
  • The Importance of AI System Memory
  • Java and Low Latency
  • Event-Driven Order Processing Program

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook