skip to content

Is MessageDigest.getInstance("SHA-256") an appropriate way to store user passwords? Explain.

level: middleimportance: must knowfreq 60%

answer

  1. Fast hash = attacker's friend (billions/sec on GPUs)
  2. No salt → rainbow tables + equal passwords collide
  3. Passwords need slow + salted + memory-hard KDF
  4. Argon2 / scrypt / bcrypt / PBKDF2
  5. MessageDigest is for integrity/fingerprinting, not secrets at rest

basics

~10 s

No. SHA-256 via MessageDigest is fast and unsalted, so attackers can brute-force or use rainbow tables. Store passwords with a slow, salted, purpose-built KDF like bcrypt, scrypt, Argon2, or PBKDF2 instead.

solid answer

~50 s

No — MessageDigest is the wrong tool for passwords. Cryptographic hashes like SHA-256 are designed to be fast and they take no salt by default, which is exactly what an attacker wants: a leaked database of raw SHA-256 hashes can be cracked at billions of guesses per second on GPUs, and identical passwords produce identical hashes, enabling precomputed rainbow-table attacks. Password storage instead needs a deliberately slow, memory-hard, salted password hashing function (a KDF): Argon2 (preferred today), scrypt, or bcrypt, or PBKDF2 with a high iteration count where a vetted library is unavailable. The salt (unique per user, stored alongside) defeats rainbow tables and ensures equal passwords hash differently; the deliberate slowness/cost factor makes large-scale brute force infeasible and is tunable upward as hardware improves. MessageDigest's legitimate role is integrity and fingerprinting of data — file checksums, content addressing, the inner hash of an HMAC — not protecting low-entropy secrets at rest.

go deeper

for a junior

Knows you must not store passwords with plain SHA-256/MD5 and should use bcrypt/Argon2 style password hashing instead.

for a middle

Explains why: fast hashes are brute-forceable and unsalted hashes enable rainbow tables; names salted, slow KDFs (Argon2/scrypt/bcrypt/PBKDF2) and MessageDigest's real role.

for a senior

Distinguishes salt vs work factor vs memory-hardness, can pick and tune a KDF, and separates password storage from integrity/HMAC use cases.

for a principal

Sets org-wide credential-storage standards (algorithm, cost parameters, migration/rehash-on-login strategy, peppering/HSM considerations) and reviews for fast-hash-for-passwords anti-patterns.

## Short answer: no — and here is why `MessageDigest.getInstance("SHA-256")` gives you a **fast, general-purpose cryptographic hash**. Those properties (speed, determinism, no salt) are great for integrity checks but are precisely the properties that make a hash **unsuitable for storing passwords**. ## What makes password storage different A password is a **low-entropy secret**: humans pick from a tiny, predictable space (`password1`, `qwerty`, dictionary words). The defender's job is to make *guessing* each password as expensive as possible, because if the hash database leaks, the attacker will try to recover the plaintext by hashing guesses and comparing. Three forces matter: 1. **Speed is the enemy.** SHA-256 is engineered to be *fast* — modern GPUs/ASICs compute **billions of SHA-256 hashes per second**. A fast hash means an attacker can test an enormous number of guesses cheaply. Password hashing wants the opposite: a function that is **deliberately slow** (tunable work/cost factor), so each guess costs real time/energy. As hardware improves, you raise the cost factor. 2. **No salt → rainbow tables and shared cracking.** Plain SHA-256 of the same password always yields the same digest. So (a) an attacker can precompute a giant table of `hash → password` (a **rainbow table**) once and reuse it against everyone, and (b) seeing two equal hashes reveals two users share a password. A **salt** — a unique random value per user, stored next to the hash — makes each user's hash unique even for identical passwords, defeats precomputation, and forces the attacker to crack each entry separately. 3. **Memory-hardness raises the bar further.** Some functions (scrypt, Argon2) are also **memory-hard** — each guess needs a lot of RAM — which neutralizes the cheap massive parallelism of GPUs/ASICs. ## The right tools (password hashing functions / KDFs) Use a **purpose-built password hashing function**, not a raw digest: - **Argon2id** — the modern recommendation (won the Password Hashing Competition); tunable time, memory, and parallelism cost. - **scrypt** — memory-hard, well-established. - **bcrypt** — battle-tested, with a built-in salt and a cost factor; caps input length (~72 bytes). - **PBKDF2** — available in the JDK (`SecretKeyFactory` with `PBKDF2WithHmacSHA256`); acceptable with a high iteration count when a memory-hard option isn't available, but it is *not* memory-hard. These all (a) take/embed a **salt**, (b) have a **tunable cost** so you can keep them slow as hardware advances, and (c) are designed specifically for low-entropy secrets. ## Why "just add a salt to SHA-256" still isn't enough Salting plain SHA-256 stops rainbow tables, but the hash is **still fast** — the attacker just cracks each salted hash individually at billions/sec. You need the *deliberate slowness/memory cost* that only a real password hashing function provides. "SHA-256 + salt" is a common interview trap; the missing ingredient is **work factor**, not just salt. ## Where MessageDigest IS appropriate MessageDigest is right when you are hashing **high-entropy or non-secret data for integrity/identity**, where speed is a feature: - File/download **checksums** and content-addressed storage (Git-style). - The internal hash inside an **HMAC** or a digital signature. - Deduplication fingerprints, ETags, cache keys. In those cases there's nothing to brute-force, so a fast hash is exactly what you want. ## The interview-grade summary Passwords: **slow, salted, memory-hard, purpose-built KDF (Argon2/scrypt/bcrypt/PBKDF2)**. Integrity/fingerprinting of data: **fast cryptographic hash via MessageDigest (SHA-256+)**. Conflating the two is one of the most common and most damaging security mistakes.

  • Isn't adding a per-user salt to SHA-256 enough?
    No. A salt defeats rainbow tables and makes equal passwords hash differently, but SHA-256 is still extremely fast, so an attacker can brute-force each salted hash at billions of guesses per second. You also need a deliberately slow, ideally memory-hard, tunable-cost function (Argon2/scrypt/bcrypt/PBKDF2).
  • Then what is MessageDigest legitimately for?
    Integrity and fingerprinting of data where speed is desirable and there is no low-entropy secret to protect: file checksums, content-addressed storage, dedup fingerprints, ETags, and as the inner hash of an HMAC or signature.

saying these in an interview costs you the question

  • Storing passwords as SHA-256 (or worse, MD5) digests
  • Claiming 'SHA-256 + a salt' is sufficient — it's still too fast (no work factor)
  • Thinking more rounds of SHA-256 by hand is equivalent to a vetted KDF
  • Reusing one global salt for all users instead of a unique per-user salt

context