Argon2 explained simply: how one password becomes an encryption key

What is Argon2? A plain-language guide to password hashing, salt and memory-hard key derivation, how it compares with bcrypt, and how Cappa uses it.

A capybara patiently turns the crank of a large old-fashioned press full of gears, feeding in a small paper slip on one side while a solid brass key comes out the other.
On this page

What is Argon2? It is a password-hashing function: a recipe that turns a password into a fixed-length string of bytes in a way that is deliberately slow and memory-hungry, so every guess an attacker makes is expensive. Argon2 won the Password Hashing Competition in 2015 and is standardized in RFC 9106. Cappa uses its Argon2id variant to turn your master password into the keys that protect your notes.

This explainer starts from zero: what a hash is, why ordinary hashes are the wrong tool for passwords, what "salt" and "memory-hard" mean, and how Argon2 compares with bcrypt, scrypt and PBKDF2. Then we follow one password, step by step, through Cappa's key derivation.

What is Argon2?

Argon2 is a key derivation function, a close cousin of a hash function built for passwords. You give it a password, a salt and a few cost settings, and it returns a result of the length you ask for. The same inputs always give the same result, and there is no practical way to run it backward.

It came out of the Password Hashing Competition, an open contest that cryptographers ran from 2013 to 2015 to find a better way to protect passwords. In July 2015 the panel announced Argon2 as the winner. In September 2021 the IETF published it as RFC 9106, the formal specification that implementations follow.

Key derivation function (KDF)
A function that turns one secret (here, your password) into cryptographic keys of a fixed size. A password-based KDF is designed to be slow on purpose, so that guessing passwords is expensive.

What a hash is: a fingerprint for data

A hash function takes any input, a word or a whole movie, and produces a short, fixed-size "fingerprint". SHA-256, one of the most common, always produces 256 bits, usually written as 64 hexadecimal characters.

Fingerprints have three useful properties. The same input always gives the same fingerprint. A tiny change gives a completely different one. And you cannot rebuild the input from the fingerprint. Here are the real SHA-256 fingerprints of two notes that differ only by one capital letter:

SHA-256("my note") = cec25c1af6f55332088bea53dfdbff1a7c168a11e6054208a288d8bacf778a90
SHA-256("My note") = db0d68b465f480cf0109b69436df7feb3a996bb371f5a144a597f51e1e4c39ab

That is why services store a hash instead of your password. At sign-in they hash what you typed and compare fingerprints. If the database leaks, the attacker gets fingerprints, not passwords.

Password hashing explained: why fast hashes are the wrong tool

You cannot reverse a hash, but you can guess. An attacker with a stolen fingerprint takes a candidate password, hashes it, and checks for a match. Then the next candidate, and the next.

SHA-256 and MD5 were designed to be fast, so that checking a large download takes a moment. That speed helps the attacker. In public hashcat benchmarks, a single RTX 4090 graphics card computes about 163 billion MD5 hashes and 22 billion SHA-256 hashes per second. At that rate, many passwords people choose fall within minutes.

Password hashing turns the problem around. The goal is a function that is fast enough for you, since you only need to compute it once when you sign in, and painfully slow for someone who needs to compute it billions of times.

Salt: the unique ingredient

If everyone's password went through the same recipe, attackers could compute fingerprints for millions of common passwords once and look up every stolen hash in that table. Two users with the same password would also have the same fingerprint, which reveals something by itself.

Salt
A value mixed into the password before hashing, unique for each account. It does not need to be secret. Its job is to make the same password produce different results for different people, so every account must be attacked separately.

Think of it as a unique ingredient added to each person's dish: two cooks using the same recipe still end up with dishes that taste different.

Cappa builds its salt from two things: your account email and a random 16-byte seed that is created again whenever you register, change your password or recover your account. The app mixes them, together with a fixed label and version number, through SHA-256. Binding the email into the salt has a specific purpose. The Argon2id settings are fixed inside the app, and the salt always includes your own address, so even a misbehaving server cannot hand many accounts the same salt or a cheaper recipe to make mass guessing easier (as long as the app code running in your browser is genuine).

Deliberately slow and memory-hungry

Making a hash slow is easy: repeat it many times. Older methods like PBKDF2 do exactly that. The trouble is that repetition only costs computing time, and graphics cards and custom chips have enormous amounts of cheap computing power running in parallel.

Argon2 also costs memory. Each run fills a large block of memory with pseudo-random data, then makes several passes over it, where each new piece depends on earlier pieces spread across the whole block. You cannot skip ahead or compute it with less memory without paying a heavy penalty in extra work.

This is what "memory-hard" means, and it is why Argon2 slows attackers far more than it slows you. With Cappa's settings, the hashcat 7.0 release notes measure about 1,703 guesses per second on the same RTX 4090 that does 163 billion MD5 guesses per second. For how that translates into time for real passwords, see how long a master password should be.

Argon2d, Argon2i and Argon2id: which variant?

RFC 9106 defines three variants. Argon2d chooses which memory to read based on the data itself, which resists graphics-card attacks well but can leak information through timing on a shared machine. Argon2i reads memory in a fixed order that does not depend on the password, which avoids that leak. Argon2id runs like Argon2i for the first half of the first pass and like Argon2d after that, combining both protections.

The RFC makes Argon2id the variant every implementation must support and the one to pick when in doubt, and the OWASP Password Storage Cheat Sheet lists it first. Cappa uses Argon2id.

The three Argon2 settings in plain words

SettingWhat it meansCappa's value
Memory (m)How big the "room" is: memory each run must fill64 MiB
Passes (t)How many times the run walks over that memory3
Parallelism (p)How many independent lanes can run at once1
Output lengthHow many bytes come out32 bytes (256 bits)

For comparison, RFC 9106's second recommended option is 64 MiB with 3 passes and 4 lanes; Cappa uses the same memory and passes with one lane, which suits a single background thread in a browser. OWASP's minimum for server-side password storage is lower (for example 19 MiB with 2 passes), because a busy server hashes passwords for many users at once.

How long does one run take? In our own test on a laptop with an Apple M4 Pro chip, one run with Cappa's settings and the same WebAssembly library the app uses took about 0.1 seconds. Older phones take noticeably longer. You pay that cost once when you unlock. An attacker pays it for every guess.

Hashing a login password vs deriving an encryption key

The same Argon2 can do two different jobs, and the difference matters.

Hashing a login password (server)

  • The server stores the hash and compares it at each sign-in
  • The server can limit attempts, lock accounts and alert you
  • Settings can be raised the next time you sign in
  • A leaked hash lets attackers guess offline

Deriving an encryption key (your device)

  • The result is not stored; it is the key that opens your data
  • Anyone holding a copy of the encrypted data can guess offline, with nobody to stop them
  • Settings are part of the data format, so changing them needs a new version
  • It runs on your own device, so it must work on modest phones

For an end-to-end encrypted app, the second job is the important one. The server never sees your password, so it cannot hash it for you. Your device has to derive the key itself, and the key derivation cost is the main thing standing between a stolen database and your notes.

Key derivation explained: how Cappa turns your password into keys

Cappa does both jobs, in this order:

Master password + salt

Your password, and a salt made from your email and a random 16-byte seed

in a Web Worker

Argon2id

64 MiB, 3 passes, 1 lane

Root key

32 bytes, split with HKDF-SHA-256 into two independent keys

authKey

Proves who you are at sign-in

HTTPS

Server

Hashes the authKey again with Argon2id and stores only that hash

Password KEK

Never leaves your browser

opens

Vault key envelope

Holds the random vault key that encrypts your notes

Cappa's key derivation (version 1). The first row happens entirely in your browser; the two rows below show where each derived key goes.
  1. Your password is prepared. The app converts it to a standard Unicode form (NFC) and encodes it as bytes. Nothing is trimmed, so spaces count.

  2. Argon2id runs in a Web Worker. A Web Worker is a background thread in your browser, so the page stays responsive while the memory-hard work runs. The result is a 32-byte root key.

  3. HKDF splits the root key in two. HKDF-SHA-256 (RFC 5869) is a fast, standard way to derive several independent keys from one strong secret. Different labels give two unrelated keys: the authKey and the password KEK (key-encryption key).

  4. The authKey proves who you are. It goes to the server as your account password. The server hashes it again with Argon2id before storing it, so a copy of the database does not contain a value that signs you in directly.

  5. The password KEK opens your vault. It never leaves the browser. It decrypts a small "envelope" that holds your vault key, a random 256-bit key that encrypts your notes with AES-256-GCM.

Knowing the authKey does not reveal the password KEK: HKDF makes them independent. Your password itself never leaves the browser. For the full picture of what the server stores, see what the server can and can't see.

Argon2 vs bcrypt, scrypt and PBKDF2

All four are respectable password-hashing functions. They differ in what they make expensive.

FunctionYearWhat it makes expensiveOWASP settings (as of September 2026)Fair verdict
Argon2id2015 (RFC 9106 in 2021)Time and a tunable amount of memoryMinimum 19 MiB, 2 passes, 1 lane (or equivalent)First choice for new systems
scrypt2009Time and memoryN=2^17 (128 MiB), r=8, p=1Strong; OWASP's pick when Argon2id is unavailable
bcrypt1999Time, with a small fixed memory (about 4 KiB)Work factor 10 or more; passwords up to 72 bytesStill acceptable for older systems; the 72-byte limit and small memory show its age
PBKDF22000Time only (repeated hashing)600,000 iterations with HMAC-SHA-256Use when FIPS-140 compliance is required; cheapest for graphics cards to attack

The OWASP numbers above come from the Password Storage Cheat Sheet, which also lists equivalent Argon2id and scrypt combinations that trade memory for passes. Those minimums target servers that hash many logins; a key derived once on your own device can afford more, which is why Cappa uses 64 MiB and 3 passes.

Argon2 vs bcrypt, in one sentence: bcrypt is a proven design from 1999 that is still fine for many logins, but Argon2id lets you choose how much memory each guess costs, which makes it a better match for today's graphics cards and for deriving encryption keys.

What slow hashing cannot do

FAQ

Is Argon2 encryption?

No. Encryption is reversible with the right key; Argon2 is a one-way function. In Cappa, Argon2id produces the keys, and a separate cipher, AES-256-GCM, does the actual encrypting.

Is Argon2 better than bcrypt?

For new systems, generally yes: OWASP lists Argon2id first and bcrypt for legacy systems. The main advantage is that Argon2id makes attackers pay in memory, not only time, and has no 72-byte password limit. A well-configured bcrypt is still far better than a fast hash.

Can an Argon2 hash be cracked?

It cannot be reversed, but it can be guessed. An attacker hashes candidate passwords and compares results. Argon2id makes each guess slow and memory-heavy, so strong, random passwords stay out of reach, while common ones still fall.

Why does unlocking Cappa take a moment?

Your device runs Argon2id with 64 MiB of memory and 3 passes each time it derives your keys. That short wait is the same cost that makes each attacker's guess expensive, which is exactly the point.

Does the server ever see my master password?

No. The server receives only the authKey derived from it, and it hashes that again with Argon2id. This relies on the app code your browser runs being genuine; code tampered with on a compromised server could capture the password.

Written by the Cappa team

We build Cappa, a private Markdown notes app that encrypts your notes on your device before they are synced. We write about the decisions behind it, including the limits, so you can judge them yourself.