AnyHash
Skip to content

Argon2id Hash & Verify

Derive a memory-hard Argon2id hash of any password — or verify an existing hash — entirely in your browser. Parameters are yours to choose: memory, iterations, parallelism, and output format, computed in a Web Worker with a WebAssembly build of the reference algorithm.

Argon2id hash

 

Enter a password and a salt to derive an Argon2id hash.

Code snippets

Generate Argon2id in your language

import argon2 from "argon2";

const hash = await argon2.hash("password");
console.log(hash);
// $argon2id$v=19$m=65536,t=3,p=4$... — random salt, every run differs

const ok = await argon2.verify(hash, "password");
console.log(ok); // true

Argon2id parameters are encoded in the leading $argon2id$ header (version, memory m, iterations t, parallelism p). The salt is random, so the output changes on every run.

How Argon2id works

Argon2id was the 2015 Password Hashing Competition winner and is today's OWASP top recommendation for password storage. Unlike bcrypt — which only burns CPU — Argon2 is memory-hard: it fills a large buffer of RAM with the password's state, then overwrites it over several passes. Every hash therefore requires both memory capacity and memory bandwidth, the two resources GPU crackers run out of first.

The tool exposes the three critical parameters — memory size (m), iterations (t), and parallelism (p) — so you can match OWASP guidance now and raise your configuration as your threat model or hardware evolves. The encoded output string records them all, so a hash remains verifiable no matter what it cost to create.

Argon2 best practices

  • Always use Argon2id — not Argon2i or Argon2d alone — for password storage
  • Stay on or above OWASP's floor: 19 MiB, t=2, p=1; prefer 64 MiB, t=3, p=4
  • Store only the encoded string; it carries the salt, version, and parameters
  • Never hash passwords with plain SHA-256 or MD5 — they are far too fast
  • Rehash old credentials on the next login to raise parameters over time

Already on bcrypt? See how to migrate — or bench a hash here and compare timings against your current cost factor.

Algorithm guide

Argon2id explained

What is Argon2id?

Argon2id is a password-hashing function derived from Argon2, the algorithm selected as the winner of the Password Hashing Competition (PHC) in 2015. The competition — organized by cryptographers including Jean-Philippe Aumasson — asked the community to design a password hashing scheme that could withstand the two threats that had broken its predecessors: fast GPU brute-forcing and cheap specialized hardware. Argon2id is the hybrid variant of Argon2, and the exact configuration the PHC winners and OWASP recommend for ordinary password storage.

Two design ideas set Argon2 apart from earlier KDFs. First, memory hardness: computing a hash must consume a large, tunable amount of RAM, so no hardware shortcut can make guesses dramatically cheaper. Second, tunable parallelism: work can fan out across up to 16 lanes, letting a single login cost seconds of sequential CPU time on ordinary hardware. The full state — password, salt, version, and parameters — is folded into a single encoded string, so a system storing Argon2 hashes needs nothing more than a text column to verify a login later.

How Argon2 works, step by step

1. Fill the memory buffer

Argon2 first derives an initial state from the password and a random salt using BLAKE2b. It then fills a buffer of m KiB — split across p parallel lanes — block by block. Each 1 KiB block is produced by permuting one or more previously written blocks: the current block plus a reference chosen from the blocks already written in this pass.

2. Overwrite it, t times

With the buffer full, Argon2 runs t passes, each pass overwriting every block. The permutation function inside each block is a compression round that mixes XOR and modular addition (a structure close to a fast, memory-hard hash like the one used by Zcash's Equihash family). Because every block's output depends on blocks computed earlier in the same run, an attacker cannot skip the fill step: the memory contents encode the password, and any shortcut that drops blocks breaks the result.

3. Squeeze the tag

After the final pass, Argon2 feeds the last block of each lane, the password length, the salt, and the parameters into a final BLAKE2b step to produce the tag — the derived key. With the encoded output format, that tag is Base64-encoded and appended to a self-describing header, which is why an Argon2id string can carry everything needed to re-derive it later.

Argon2d, Argon2i, Argon2id — which variant?

The three Argon2 variants differ only in how each block chooses its references, and that small difference has real security consequences:

  • Argon2d picks references data-dependently — using the previous block's contents as the address of the next source block. This maximizes resistance to time-memory tradeoff attacks and GPU cracking, but the data-dependent addressing leaks timing information through CPU cache behavior. A process that can co-locate on your machine and observe cache misses could, in principle, learn about the password.
  • Argon2i picks references data-independently, using a fixed pseudo-random schedule derived only from the salt and inner state. This is immune to cache-timing side channels, which made it the PHC entrants' safe choice — but an attacker with a large enough budget can exploit the predictability with a time-memory tradeoff attack at lower cost than against Argon2d.
  • Argon2id hybridizes the two: the first half of the first pass uses data-independent (Argon2i-style) addressing, and everything after is data-dependent (Argon2d-style). It captures most of Argon2i's side-channel resistance while keeping most of Argon2d's tradeoff resistance. For password hashing on multi-user servers, it is the configuration everyone — the PHC, OWASP, and RFC 9106 — recommends you actually use.

The rule of thumb: use argon2id for password storage and password-based key derivation. Reaching for Argon2i is defensible only in threat models dominated by side-channel attacks (shared, untrusted execution environments); Argon2d is reserved for environments where even an active attacker cannot observe timing — a rare guarantee.

m, t, p — the three knobs that control the cost

Argon2's cost is described by three integers, all exposed in this tool:

  • m — memory in KiB. The buffer size. Every hash must actually allocate and write this much memory, so it is the parameter that most directly determines brute-force cost. Raising m from 19 MiB to 64 MiB does not merely slow a targeted attack — it changes which hardware is viable at all, because GPUs have limited on-card memory and memory bandwidth is shared across every concurrent guess.
  • t — iterations. Number of full passes over the buffer. Each extra pass multiplies compute time and memory traffic without consuming more RAM. On a CPU, t is cheap and safe to raise when you need more work than memory allows; the tradeoff is that high t does slightly less to resist memory-as-ASIC attackers than a corresponding increase in m.
  • p — parallelism / lanes. Number of independent lanes the memory buffer is split across; they are combined at the end into the single final block. Higher p lets a server with many cores service logins in less wall-clock time per CPU core, at no security cost. It is safe to keep at 1 if you only sign in on one device; large deployments benefit from 4.

The fourth field in this tool, hash length, sets the tag size in bytes. The default of 32 bytes (256 bits) is a deliberate choice: it is the maximum supported by the reference implementation for standard password hashing and gives a comfortable margin against brute-forcing the tag itself. Lower values (16) match older applications; higher values add no security for password storage.

OWASP & RFC 9106 — sane starting points

Instead of reasoning about m, t, p from scratch, start from the two published recommendations this tool's presets follow:

SourceMemorytpUse case
OWASP minimum19 MiB (m=19456)21Absolute floor for any Argon2id deployment
OWASP recommended64 MiB (m=65536)34New systems with normal login volume
RFC 9106 interactive64 MiB (m=65536)34Low-memory configuration for interactive logins
High security128 MiB (m=131072)44Backend/admin or batch hashing with generous RAM

The OWASP Password Storage Cheat Sheet has treated these figures as the reference guidance since 2021: 19 MiB / t=2 / p=1 is the documented floor, and 64 MiB / t=3 / p=4 is the recommended default for new applications. RFC 9106 (the Argon2 RFC) independently describes a comparable interactive-login configuration. Any configuration at or above the floor is a defensible choice; the presets in this tool exist so you can toggle between the two published benchmarks and a high-security option without doing the math by hand.

Argon2id vs bcrypt vs scrypt vs PBKDF2

Argon2idbcryptscryptPBKDF2
Year2015199920092000
Deliberate costCPU + memory + threadsCPU (iterations)CPU + memoryCPU (iterations)
GPU/ASIC resistanceVery highModerateHighLow
Side-channel sensitivityLow (Argon2id hybrid)LowLowLow
Input limitsNone practical72 bytesNone practicalNone practical
Library availabilityGrowing (most languages)Every major languageMost languagesEvery major language
OWASP recommendationRecommendedAccepted (legacy)AcceptedAccepted

The table explains the modern hierarchy in one glance. PBKDF2 remains mandatory in some compliance regimes but is weakest against modern hardware. bcrypt adds salt and CPU deliberate slowness but caps inputs at 72 bytes and has no memory cost at all. scrypt introduced memory-hardness and is good in constrained environments, but its memory addressing is data-dependent-only and it never received the breadth of independent analysis Argon2 has. Argon2id is the strongest overall configuration currently standardized, which is why the direction of travel for new systems is unambiguous.

Why memory hardness actually wins

The history of password cracking is a race between scheme and hardware. MD5 and SHA-256 are CPU-bound: a modern GPU evaluates billions per second because the computation fits in registers and leaks nothing to shared memory. bcrypt raised the CPU cost enormously, but the load is still just CPU cycles — an expensive FPGA or ASIC can pack many bcrypt cores on a die and restore most of the lost throughput.

Argon2 changes the game by requiring memory. A single Argon2id hash at 64 MiB must write and then read roughly 64 MiB × t of RAM. On a GPU, RAM is off-die and bandwidth is the shared bottleneck for every core in a cracking rig; an attacker amortizing thousands of concurrent guesses across one card soon finds the bus saturated. The classic escape hatch — the time-memory tradeoff, computing the hash with less memory in exchange for more compute — is exactly what data-dependent addressing in Argon2d and the hybrid Argon2id is designed to frustrate. Making guesses expensive in RAM is what turned password databases from "crackable overnight" into "crackable only with extraordinary budgets".

Memory hardness does carry one operational cost: a flood of login attempts consumes genuine RAM per request, so a misconfigured high m can itself enable a denial-of-service attack at the application layer. That tradeoff is the reason OWASP's floor is deliberately moderate — 19 MiB is enough to hurt crackers while remaining cheap enough that a busy login path cannot exhaust a normal server's memory.

How the AnyHash Argon2id tool works

  • WebAssembly, not a reimplementation. The hash is computed with hash-wasm, a versioned WebAssembly build of the Argon2 reference implementation. Results match any other conforming library — Python's argon2-cffi, Node's argon2, or the reference CLI — bit for bit.
  • A Web Worker keeps the page alive. Secure parameters take hundreds of milliseconds to a second and tens of MiB of memory. Instead of freezing the main thread, the derivation runs in a dedicated Worker, so you can keep typing, scroll, and read the guide while the hash computes.
  • Cryptographically random salt. The salt field is prefilled with 16 random bytes (32 hex characters) from crypto.getRandomValues. The Random button regenerates it; a fresh salt for every hash is what makes identical passwords produce unrelated outputs.
  • Encoded or raw output. Encoded mode returns the self-describing $argon2id$… string that production systems store; hex mode returns the raw tag for applications that manage salt and parameters themselves.
  • Nothing leaves your device. There is no network call in the hashing path — the page, the Worker, and the WASM module are all loaded from the site itself, and the password never appears in a form submission.

Reading an Argon2id hash string

An encoded Argon2id hash is a single string with five segments separated by $. Take this example for the password correct horse battery staple at the OWASP-recommended settings:

$argon2id$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$qEAsQ6mHvtP/…tag…
  • argon2id — the algorithm identifier (argon2d, argon2i, or argon2id)
  • v=19 — the version number (0x13); version 19 is the current standard after a bug fix in early multi-lane implementations
  • m=65536,t=3,p=4 — memory in KiB, iterations, and parallelism
  • c2FsdHNhbHRzYWx0c2FsdA — the salt, Base64-encoded without padding
  • the final segment — the derived tag, Base64-encoded without padding

Try it: paste the example into this page's verify tab with the password above. Because the string records everything needed — salt, version, and parameters — verification needs no external metadata. Any compliant verifier, on any platform, will re-derive the same tag.

Verification, deep dive

The verify tab performs exactly the operation a production login flow performs: argon2Verify(password, hash) from the same WebAssembly module. The module parses the encoded string, reads the salt and parameters, re-runs Argon2id at exactly those settings, derives the tag, and compares it against the stored tag. The comparison is done in constant time, so a local check leaks no byte-by-byte information about the tag.

This is also why upgrading parameters is safe: verification always runs at the parameters written inside the hash, not at whatever the server is configured to use today. When you decide to raise m from 19 MiB to 64 MiB, old hashes still verify correctly, and at their original lower cost. This is precisely why the upgrade pattern is “rehash the password on the next successful login” rather than “reset every password”.

Benchmark before you ship

A good configuration is the highest one your real login path can bear. This page reports the wall-clock time for every hash — use it to calibrate before committing a parameter set to production:

  1. Run a hash at the OWASP floor (19 MiB, t=2, p=1) and at the recommended 64 MiB, t=3, p=4. Note the difference on this device.
  2. Decide how much of your peak concurrent login load the server must serve — memory multiplies: 1,000 concurrent logins at 64 MiB is a 64 GiB working set.
  3. Pick the highest configuration where worst-case verification stays within your SLO — OWASP suggests aiming for at least a quarter of a second on ordinary hardware, and few sites benefit from going beyond roughly a second.
  4. Re-benchmark annually and after hardware changes; raising parameters later is safe because the cost is embedded in each hash.

Because the browser and the server both run the reference algorithm, a timing measured here closely approximates a native implementation on the same CPU — a reasonable, if not perfect, proxy for what your production server will see.

Migrating from bcrypt to Argon2id

bcrypt remains a solid legacy choice (see our bcrypt guide), but every new system should default to Argon2id. If you already store bcrypt hashes, use the compare-and-upgrade pattern: verify as you do today, and only when the password matches, derive an Argon2id hash at your new parameters and store it beside the old one. Each user migrates on their next successful login, with no forced resets and no readable-plaintext moment. New accounts and password changes should be hashed with Argon2id from day one.

The main reasons a team stays on bcrypt are library availability in an ancient stack and a conservative change control culture — both legitimate, both increasing in friction with every year. Modern frameworks (Laravel, Django, ASP.NET Core, and most runtimes) now ship Argon2id natively or one dependency away. Bench the parameters here, run the upgrade in a canary slice, and let the embedded self-describing format carry the old hashes forward while the new ones take over.

Frequently asked questions

What is Argon2id?

Argon2id is the winner of the 2015 Password Hashing Competition and the current OWASP-recommended password KDF. It is a memory-hard function that requires a tunable amount of RAM and CPU time to compute, which makes brute-forcing stolen password hashes expensive.

How much memory should I use for Argon2id?

OWASP defines 19 MiB (m=19456), t=2, p=1 as the absolute minimum, and recommends 64 MiB (m=65536), t=3, p=4 for new systems that can afford it. Memory matters: more KiB per hash means each guess costs proportionally more, which is exactly what stops GPU password cracking.

Can Argon2id hashes be reversed?

No. Argon2id is one-way, and it derives a fresh random-looking tag for every unique salt. Combined with its memory hardness, there is no shortcut faster than brute-force guessing — which the parameters are tuned to make impractically slow.

What is the difference between Argon2d, Argon2i, and Argon2id?

Argon2d is data-dependent (fastest against GPUs but side-channel sensitive), Argon2i is data-independent (side-channel resistant but weaker against tradeoff attacks), and Argon2id hybridizes both — data-independent for the first half of the first pass, data-dependent after. Argon2id is the recommended default.

Why does Argon2id run in a Web Worker instead of the main thread?

Argon2id at secure parameters consumes tens of MiB of memory and can take hundreds of milliseconds to a second. Running it in a Web Worker keeps the page responsive, and the underlying WebAssembly build of the reference algorithm is used so results match other conforming implementations exactly.

Other hash tools