Encryption & Security

Hashing, Salting & Key Derivation

Not everything in security is about locking and unlocking. Some of the most important tools are one-way: they produce fingerprints that can be checked without decrypting anything. Password hashing makes guesses more expensive; key derivation prepares secrets for encryption. Neither can turn a predictable password into an unguessable secret. Here's how the pieces fit together.

Hash function
A fixed-length fingerprint. Computing it is fast; finding an input for an arbitrary digest should be infeasible. NDEVR uses SHA-256 and SHA-512.
Password protection
Slow password processing raises guessing costs. OWL’s OPAQUE suite uses Argon2id.
Key derivation
Derives keys for specific uses. OWL uses HKDF for key separation and PBKDF2 in recovery-key envelopes.
Salt
A per-record value that prevents reuse of the same password-hashing computation across records; it need not be secret.

What is a Hash?

A hash function takes any input — a word, a password, a gigabyte file — and produces a fixed-size string of bytes called a digest. Three properties make it useful:

  • One-way. Easy to compute; designed to make finding an input for a given digest infeasible. A short list of likely inputs can still be tried.
  • Deterministic. The same input always yields the same hash — so you can compare fingerprints instead of the originals.
  • Avalanche effect. Change a single character and the entire hash changes unrecognizably.

Crucially, a hash is not encryption: there is no key and no way to “decrypt” it. It's a fingerprint, not a locked box.

SHA-256, the Fingerprint

SHA-256, part of the SHA-2 family, produces a 256-bit digest. It is useful for fingerprints and integrity checks when the expected digest comes from a trusted source. A bare hash does not prove who created a file: someone who can replace both the file and its digest can make them match. Authentication needs a keyed construction such as HMAC, an authenticated-encryption tag, or a digital signature.

Passwords, Salt & OPAQUE

A conventional password-hash login stores a salted verifier rather than the plaintext password. At login, it processes the supplied secret again and compares the result. Two problems shape that design:

  • Unsalted passwords share a hash. Without distinct salts, two users who both pick “password123” have matching stored hashes — and attackers can precompute giant tables (“rainbow tables”) of common passwords. The fix is a salt: a unique random value mixed in before hashing, so an attacker must do work for each salt instead of reusing one precomputed table across accounts.
  • Fast hashes are too fast. A general-purpose hash like SHA-256 is built for speed, which lets an attacker try billions of guesses per second. Password hashing should be deliberately slow.

bcrypt combines a salt with an adjustable computational cost. Argon2id also makes memory consumption part of the cost. Both make guessing more expensive; neither removes the need for a strong password. A password-hashing function alone does not keep a password hidden from the server receiving it. OPAQUE changes the login protocol so the device can authenticate without sending the password.

★

A salt is public; a password is secret

Use a fresh, sufficiently long random salt for each password-hash record. Store it with the result: secrecy is not its job. Its job is to separate records and prevent reusable precomputation. It does not stop an attacker from guessing a weak password one candidate at a time.

Turning Secrets Into Keys

Encryption needs uniform, full-length keys, but the secrets we start with — a password, or the raw output of a key exchange — usually aren't in that shape. A key derivation function (KDF) bridges the gap. These functions have different jobs:

  • Argon2id — a memory-hard function that makes each guess consume memory as well as computation. OWL’s OPAQUE suite applies it to the OPRF-derived result, using 64 MiB of memory, three passes and one lane. See RFC 9106 for Argon2’s design.
  • PBKDF2 (Password-Based Key Derivation Function 2) — repeats a keyed hash to increase derivation cost. OWL uses PBKDF2-HMAC-SHA256 in its separate user-held recovery-key envelopes. A KDF can also process a strong random recovery secret; it is not limited to human passwords.
  • HKDF (HMAC-based KDF) — for deriving keys from a high-entropy secret that's already strong but not uniformly shaped, such as the shared secret produced by an ECDH key agreement. HKDF “extracts and expands” that secret into one or more clean keys. It separates keys by purpose, but does not add password-guessing resistance. It should not replace a password-stretching function.

How NDEVR Uses Them

OWL combines these tools for separate purposes. Its OPAQUE sign-in uses an oblivious pseudorandom function and Argon2id, and returns a client-only export key. In OWL’s OWPK v2 format, HKDF-SHA256 derives an AES-256-GCM wrapping key from that export key to protect the account’s private key. The server stores the encrypted envelope; the device opens it. HKDF also derives the wrapping keys used by ECIES, while the user-held recovery key protects a separate recovery envelope. Password authentication, account-key protection and file encryption each have a distinct role.

References & Further Reading