TechEarl

How to Crack a bcrypt Hash (and Why It's So Slow)

bcrypt is the hash you mostly cannot crack, and that is the point. I cover the hashcat command (-m 3200), why bcrypt is deliberately glacial, how the cost factor multiplies crack time, realistic GPU expectations, and the only attack worth running against it. Tested on hashcat 7.1.2.

Ishan Karunaratne⏱️ 8 min readUpdated
Share thisCopied
Crack bcrypt with hashcat -m 3200, understand why it is thousands of times slower than MD5, what the cost factor does to crack time, and the only attack that makes sense.

bcrypt is the hash you mostly cannot crack, and that is exactly why it is everywhere. It is the default in WordPress since 6.8, in Laravel, in Spring Security, in htpasswd, in countless frameworks, precisely because it is deliberately, painfully slow. Where MD5 lets a GPU try billions of guesses a second, bcrypt drags that down to thousands. This guide shows you the hashcat command, proves how slow it is with a real crack, and explains why "run a wordlist and accept the strong ones survive" is the correct strategy, not a cop-out. Tested on hashcat 7.1.2.

TL;DR

bcrypt is hashcat mode -m 3200. The command is hashcat -m 3200 -a 0 hashes.txt rockyou.txt -r rules/best66.rule. But understand what you are signing up for: bcrypt is a slow hash by design, so you get thousands of guesses per second, not billions. That makes brute force and big masks hopeless; the only sane attack is a strong wordlist plus rules, which cracks the weak passwords and leaves the strong ones standing. The hash carries a cost factor ($2b$12$... means cost 12), and every increment doubles the work. That is the whole defence, and it works.

Identify it first

bcrypt is unmistakable. The hash is 60 characters and starts with $2, then a variant letter, then the cost:

text
$2b$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
 │  │  └─ 22-char salt + 31-char hash, base64
 │  └──── cost factor: 12 (means 2^12 = 4096 key-expansion rounds)
 └─────── variant: $2a$, $2b$, $2y$ are all bcrypt (-m 3200)

$2a$, $2b$, and $2y$ are all bcrypt and all use -m 3200. The two-digit number after the variant is the cost factor, and it is the single most important thing on the line: it sets how slow the hash is. If you are not sure what you are holding, run it through hash identification first.

Why bcrypt is so slow (on purpose)

A password hash has a job no general-purpose hash has: it must be expensive to compute. MD5 was built to be fast (megabytes of data hashed per millisecond), which is a catastrophe for passwords, because fast for the defender means fast for the attacker too.

bcrypt is built on the Blowfish cipher's key schedule, which is intentionally slow to set up, and it repeats that setup 2^cost times. Crucially the cost is tunable: a defender picks a cost where a single login takes maybe 100 to 250 milliseconds, an imperceptible delay for one user logging in, but a wall for an attacker who needs to try billions. There is no shortcut, no GPU-friendly parallel trick that collapses the work. That asymmetry is the entire design.

The only attack that makes sense

Here is a real bcrypt crack. The hash below is a cost-5 bcrypt of the word hashcat (cost 5 is unrealistically low, chosen so this finishes instantly for the demo):

bash
echo '$2a$05$LhayLxezLhK1LhWvKxCyLOj0j1u.Kj0jZ0pEmm134uzrQlFvQJLF6' > bcrypt.hash
hashcat -m 3200 -a 0 bcrypt.hash rockyou.txt

It cracks, and the status line tells the real story:

text
$2a$05$LhayLxezLhK1LhWvKxCyLOj0j1u.Kj0jZ0pEmm134uzrQlFvQJLF6:hashcat

Status...........: Cracked
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Speed.#02........:       56 H/s

Fifty-six hashes per second. That is not a typo and it is not slow hardware, that is bcrypt at a low cost on a capable machine. Compare it to MD5 on the same box, which runs in the billions. Now remember real bcrypt uses cost 10 to 12, not 5.

So the strategy writes itself. You cannot brute force at 56 (or even a GPU's few hundred thousand) guesses per second; the keyspace is too big. What you can do is run your best wordlist with good rules:

bash
hashcat -m 3200 -a 0 hashes.txt rockyou.txt -r rules/best66.rule

This tries the few million passwords people actually reuse, mutated into their common variants. It cracks password123 and Summer2024! in minutes and never touches the random 16-character ones, which is fine, because those are out of reach and you should not waste a week confirming it.

What the cost factor does to your crack time

The cost factor is exponential. Each +1 doubles the work, so the gap between a low-cost and a high-cost bcrypt is enormous:

CostRelative workVersus cost 5
51xbaseline (the demo above)
88x8 times slower
1032x32 times slower
12 (common default)128x128 times slower
14512x512 times slower

On a single modern GPU, bcrypt at the low end runs in the low hundreds of thousands of guesses per second, and every cost increment roughly halves that. Against cost 12, a real-world setting, even a strong rig is doing low thousands per second. A wordlist still works; brute force is centuries. For full benchmark numbers across GPUs, see the hashcat GPU benchmark deep dive.

The modern angle: this is what protects most logins

bcrypt is not academic. It is what is standing between an attacker and the passwords in a huge share of real systems:

  • WordPress switched its default from the old phpass hash to bcrypt in version 6.8 (2025). A WordPress database stolen today is mostly bcrypt, which is why those dumps no longer crack the way they did a decade ago.
  • htpasswd (Apache), Laravel, Spring Security, and most modern frameworks use bcrypt or Argon2 by default.

If you are storing passwords, this is the takeaway from the attacker's side: pick bcrypt at cost 10 to 12 (or Argon2id) and most of your users' passwords become uncrackable even after a breach. The how-to is in storing a bcrypt hash in MySQL and in PostgreSQL, and the column-type question is answered in what column type a password should be.

Where to go next

Sources

Authoritative references this article was fact-checked against.

Tagsbcryptpassword crackinghashcatmode 3200slow hash

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Software Systems Architect · Senior Software Engineer · Engineering Leadership

Software systems architect and senior software engineer with more than two decades designing, building, and running production software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Now a CTO, though what I write here is drawn from the full arc of that work, across architecture, engineering, and operations, not any single job.

Keep reading

Related posts

Why MD5 falls in seconds, the optimal hashcat attack (-m 0), salted MD5 variants, the truth about MD5 decrypt sites, and why no app should store passwords as MD5.

How to Crack an MD5 Hash with Hashcat

MD5 is the easy case: fast, unsalted, and broken for passwords, which makes it the perfect place to learn cracking. I cover the hashcat command, salted MD5 variants, why MD5 decrypt sites are not what they claim, and why MD5 has no business storing a password. Tested on hashcat 7.1.2.

Where Windows NTLM hashes come from, why they fall fast, the optimal hashcat attack (-m 1000), realistic crack times on modern GPUs, and how NTLM differs from NetNTLMv2.

How to Crack NTLM Hashes with Hashcat

NTLM is the hash behind Windows and Active Directory passwords, and it is fast and unsalted, which is why a password audit cracks weak ones in seconds. I cover the hashcat command, where the hashes come from, realistic crack times, and the NetNTLMv2 distinction. Tested on hashcat 7.1.2.

How to store a bcrypt password hash in PostgreSQL: the 60-character modular-crypt format, why text beats char(60), app-side hashing, the pgcrypto crypt() and gen_salt('bf') option, and a worked users-table schema.

How to Store a bcrypt Password Hash in PostgreSQL

A bcrypt hash is a fixed 60-character string. In PostgreSQL the right column is text (varchar(255) is equivalent). Why text over char(60), app-side hashing, the pgcrypto crypt() option, and a worked users schema.