Kdf unstable
Key derivation: HKDF, PBKDF2, and Argon2id.
The Kdf service derives bytes from a secret with an algorithm value
such as hkdfSha256, pbkdf2Sha256, or argon2id(). The
output is plain bytes: turn it into a typed key with the target family's raw
constructor, such as Mac.key.
Gotchas
- The secret is bytes, with no string overload. Encode passwords yourself, and normalize their Unicode form first if users type them on different platforms.
layerWebCryptodoes not provide Argon2id, because WebCrypto has no Argon2. Deriving with it fails with anUnsupportedreason, so programs can fall back to PBKDF2.NodeCrypto.layerKdfprovides Argon2id on Node.js 24.7 or later and Bun 1.4.
Algorithms
Builds an Argon2id algorithm, with memory in KiB.
Details
Omitted costs default to RFC 9106's second recommended setting: 64 MiB of
memory (65_536), 3 passes, and 4 lanes.
Gotchas
Kdf.layerWebCrypto does not provide Argon2id. Use NodeCrypto.layerKdf,
or fall back to PBKDF2 on the Unsupported reason.
Signature
declare function argon2id(options?: { readonly memory?: number; readonly parallelism?: number; readonly passes?: number;}): Argon2idBuilds the HKDF algorithm for a hash.
Signature
declare function hkdf(hash: Algorithm): HkdfHKDF with SHA-1.
Signature
declare const hkdfSha1: HkdfhkdfSha256
unstableHKDF with SHA-256.
Signature
declare const hkdfSha256: HkdfhkdfSha384
unstableHKDF with SHA-384.
Signature
declare const hkdfSha384: HkdfhkdfSha512
unstableHKDF with SHA-512.
Signature
declare const hkdfSha512: HkdfBuilds a PBKDF2 algorithm for a hash and an iteration count.
Details
Deriving with an iteration count outside 1 to 2^31 - 1 fails with an
InvalidArgument reason.
Signature
declare function pbkdf2(options: { readonly hash: Algorithm; readonly iterations: number;}): Pbkdf2pbkdf2Sha256
unstablePBKDF2 with SHA-256 at 600,000 iterations, OWASP's current figure.
Signature
declare const pbkdf2Sha256: Pbkdf2Layers
layerWebCrypto
unstableLayer that provides Kdf on the WebCrypto reference.
Details
HKDF and PBKDF2 run on crypto.subtle, off the event loop where the runtime
supports it. Argon2id fails with an Unsupported reason.
Signature
declare const layerWebCrypto: Layer.Layer<Kdf>Models
A key derivation algorithm.
Signature
type Algorithm = Hkdf | Pbkdf2 | Argon2idArgon2id (RFC 9106) with its cost parameters, from argon2id.
Details
memory is in KiB, passes is the number of passes over the memory, and
parallelism is the number of lanes.
Signature
interface Argon2id { readonly _tag: "Argon2id"; readonly memory: number; readonly name: string; readonly parallelism: number; readonly passes: number;}HKDF (RFC 5869) with a hash, from hkdf.
Signature
interface Hkdf { readonly _tag: "Hkdf"; readonly hash: Algorithm; readonly name: string;}PBKDF2 (RFC 8018) with a hash and an iteration count, from pbkdf2.
Signature
interface Pbkdf2 { readonly _tag: "Pbkdf2"; readonly hash: Algorithm; readonly iterations: number; readonly name: string;}Services
Service that derives bytes from a secret.
Signature
declare class Kdf extends Shape<"effect/crypto/Kdf", { readonly derive: (algorithm: Algorithm, secret: Uint8Array, options: { readonly info?: Uint8Array<ArrayBufferLike>; readonly length: number; readonly salt: Uint8Array; }) => Effect<Uint8Array<ArrayBufferLike>, CryptoError>;}, this> { constructor(_: never);}Example Deriving a key with HKDF
import { Effect } from "effect"import { Kdf } from "effect/crypto"
const program = Effect.gen(function*() { const kdf = yield* Kdf.Kdf return yield* kdf.derive(Kdf.hkdfSha256, new Uint8Array(32), { salt: new Uint8Array(16), info: new TextEncoder().encode("encryption"), length: 32 })})
const bytes = await Effect.runPromise(program.pipe(Effect.provide(Kdf.layerWebCrypto)))bytes.length // => 32