---
title: "PBKDF2"
description: "HMAC run a few hundred thousand times. The NIST password KDF with a salt and iterations and a choice of hash"
canonical_url: "https://hashes.agntn.dev/algorithms/pbkdf2"
---
# PBKDF2

> HMAC run a few hundred thousand times. The NIST password KDF with a salt and iterations and a choice of hash

<algorithm-facts name="pbkdf2">



</algorithm-facts>

PBKDF2 runs HMAC over the password and salt, then again over the result, `iterations` times, and XORs the rounds together. It's slow by counting, not by memory, so GPUs love it more than scrypt. Still everywhere: WPA2, BIP39 seeds (2048 rounds of HMAC-SHA512), most password stores from before 2015.

```ts
create("pbkdf2").hash("password", {
  salt: "73616c74",
  iterations: 4096,
  digest: "sha256",
  keyLength: 32,
}).digest;
// "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a"
```

`73616c74` is `salt` in hex. `digest` picks the HMAC underneath: `sha256`, `sha384`, `sha512` (the default), `sha3-256`, `sha3-512` or `whirlpool`. Whirlpool, of all things? VeraCrypt still derives volume header keys with it. The default 600000 iterations is OWASP's number for HMAC-SHA256. With SHA-512 OWASP asks for 220000, so the default errs slow, which is the right way to err. The page above uses 1000 for its sample, so it renders in a blink instead of a second.


## Sitemap

See the full [sitemap](https://hashes.agntn.dev/sitemap.md) for all pages.
