DevTools Hub

Search tools

Search for a developer tool

scrypt Explained

Part of the Hashing Toolkit

Before Argon2, before the Password Hashing Competition even existed, there was scrypt — the first widely-adopted password hashing algorithm built specifically to be memory-hard, not just slow. Argon2 Explained covers the newer, PHC-winning design in detail; this is the one that came first and proved the idea worked.

Built for a backup service, not a password field

Colin Percival designed scrypt in March 2009 for his own product, Tarsnap, an online backup service — the goal was a key derivation function that made custom-hardware brute-force attacks against a user's backup encryption key genuinely expensive, not just slower than a fast hash. That it turned out to be exactly what password storage needed too came later; the IETF standardized it as RFC 7914 in 2016, seven years after it was already in production use.

Three phases: expand, mix, combine

Unlike Argon2, which is one purpose-built construction top to bottom, scrypt is built from existing primitives in three distinct steps:

  1. Expand. A single pass of PBKDF2-HMAC-SHA256 turns the password and salt into p blocks of raw material — not for its iteration count (there's only one iteration here), just to deterministically stretch the input into the right amount of pseudorandom bytes to work with.
  2. Mix. Each of those p blocks goes through ROMix, scrypt's actual memory-hard core, independently.
  3. Combine. A second, final PBKDF2-HMAC-SHA256 pass folds ROMix's output back down into the requested output length.

PBKDF2 here is doing plain key-stretching bookkeeping on either end — all of the actual cost, and all of the memory-hardness, comes from the ROMix step sandwiched in the middle.

ROMix: the memory-hard core

ROMix works in two passes over an array V of N blocks:

  • Fill: compute block 0, then block 1 from block 0, then block 2 from block 1, and so on — each of the N blocks in V depends on the one before it, computed via BlockMix. This has to happen sequentially; block 500 can't be computed without having already computed block 499.
  • Mix: run N more rounds, each one reading a pseudorandomly chosen block back out of V — the index to read is derived from the current running value — and combining it in via BlockMix again.

That second pass is the actual point: since which block of V gets read next depends on data you don't know in advance, an implementation either keeps the entire N-block array in memory, or it has to be prepared to recompute any block on demand — and recomputing block k means redoing the sequential fill up to that point all over again. There's no shortcut; the cheapest way to answer "what's in slot 12,847" is to already have it sitting in RAM.

BlockMix itself is built from Salsa20/8 — a round-reduced version (8 rounds instead of the full 20) of the Salsa20 stream cipher. This is a real point of difference from Argon2, which builds its compression function on BLAKE2b: scrypt's core comes from stream-cipher lineage, Argon2's from hash-function lineage. Both approaches work; they just come from different corners of cryptography.

The three parameters — and a real difference from Argon2

Total memory used works out to 128 × N × r × p bytes:

  • N — the cost parameter, must be a power of 2. This is the one that controls V's size, and it's the main memory dial.
  • r — block size multiplier; each block in V is 128r bytes. Tunes how much memory bandwidth each individual operation needs, which matters for resisting certain classes of hardware optimization.
  • p — parallelization: run p independent ROMix computations. RFC 7914's reference implementation notes these can be run either sequentially (same memory, p times the wall-clock time) or in parallel (p times the memory, same wall-clock time) — the choice belongs to whoever's running it, attacker included, which is exactly why OWASP's guidance keeps p at 1 and does the real tuning through N and r instead of relying on parallelism to add cost.

Here's the difference worth knowing if you've read Argon2 Explained already: Argon2 decouples memory (m) from time (t) into two independent knobs. scrypt can't — N controls memory and ROMix's round count at the same time, since both the fill and mix passes run N times. Raising memory in scrypt always raises time right along with it; there's no scrypt equivalent of Argon2's "same memory, more passes" tuning.

Recommended parameters

OWASP's current baseline is N=2¹⁷ (128 MiB), r=8, p=1 — the same numbers already used throughout Password Hashing Best Practices. RFC 7914's own guidance is similar in spirit: it calls r=8, p=1 a good starting point for typical interactive use, while noting explicitly that the right values shift over time as memory and parallel compute both get cheaper — the same "treat it as a floor, not a target" principle that applies to every algorithm in this series.

Try it yourself

Password Hash Generator computes real scrypt hashes with configurable N, r, and p, so you can see exactly how each parameter changes the output and the timing. It runs entirely in your browser.

Related tools