Architecture and Security Foundations of the Bcrypt KDF
The bcrypt password hashing function was developed in 1999 by Niels Provos and David Mazières for the OpenBSD operating system as a direct response to vulnerabilities in traditional UNIX crypt() and unsalted single-iteration digest algorithms. While general-purpose cryptographic hash functions (such as MD5, SHA-1, and SHA-256) were optimized for maximum packet-throughput in digital signature verification and checksum integrity, bcrypt was specifically engineered to be computationally expensive and memory-bound.
At the core of bcrypt lies the Eksblowfish (Expensive Key Schedule Blowfish) cipher algorithm. Standard Blowfish utilizes a key expansion phase that computes thirty-two 32-bit subkeys and four 256-entry S-boxes ($4 \times 256 = 1,024$ 32-bit words). Eksblowfish modifies this setup by introducing an exponential cost parameter 2cost that repeatedly re-keys the state with both the password and a 128-bit cryptographically random salt. This creates a stateful internal memory requirement that severely limits the effectiveness of custom Application-Specific Integrated Circuits (ASICs) and graphics processing units (GPUs).
Anatomy of the Modular Crypt Bcrypt String
Every standard bcrypt hash consists of a string exactly 60 ASCII characters long formatted in four distinct sections separated by dollar signs ($):
- Prefix Identifier ($2a$, $2b$, or $2y$): Specifies the algorithm specification revision. Revision
$2a$is standard;$2y$is a PHP compatibility alias;$2b$is the modern standard addressing edge-case byte wraparounds. - Work Factor / Cost (2 digits): The base-2 logarithm of the iteration count. A value of
10represents $2^10 = 1,024$ rounds. A value of12represents $2^12 = 4,096$ rounds. - Salt (22 characters): A 128-bit (16-byte) random initialization vector encoded into a modified 64-character base64 alphabet (using characters
./A-Za-z0-9). - Ciphertext Hash (31 characters): The resulting 184-bit output derived from encrypting the 24-character plaintext string
"OrpheanBeholderScryDoubt"64 times with the finalized Eksblowfish subkeys.
Comparative Evaluation: Password Hashing Algorithms
| Algorithm | Primary Defense | Memory Hardness | Max Password Length | OWASP / NIST Status |
|---|---|---|---|---|
| Bcrypt | Eksblowfish Key Schedule (2cost) | 4 KB (moderate) | 72 Bytes (strict truncate) | Recommended (Cost ≥ 10) |
| Argon2id | Memory-Hard + Time-Hard Matrix | Configurable (16 MB - 64 MB) | Unlimited (< 4 GB) | Gold Standard (PHC Winner) |
| PBKDF2-HMAC | Iterative Hash Cycles ($N \ge 600,000$) | None (0 KB overhead) | Unlimited | Compliant (FIPS 140-3) |
| SHA-256 / MD5 | None (Zero work factor scaling) | None | Unlimited | Forbidden for Passwords |
The 72-Byte Truncation Limit Caveat
Due to the internal Blowfish key schedule mechanics, bcrypt only reads up to the first 72 bytes of any input password. Any characters beyond byte 72 are silently discarded during the Eksblowfish setup. In modern high-security authentication systems requiring arbitrarily long passphrases, developers frequently apply a pre-hashing step: the user's password is first digested via SHA-256 or SHA-512 into a fixed 32-byte or 64-byte binary seed before being passed to bcrypt. This guarantees uniform key distribution without exceeding the 72-byte architectural threshold.