Argon2id Key Derivation
The Password-Hashing Champion, Now a ComfyUI Node
- message
- salt
- ad
- secret
- derived_key
Argon2id is the modern answer to "turn a human-memorable phrase into a cryptographic key." It won the Password Hashing Competition in 2015, and it's the thing you should be reaching for instead of sloppy homegrown key-stretching. Its trick is being memory-hard: deriving a key burns a deliberate chunk of RAM plus CPU time, which makes brute-forcing expensive in a way that plain repeated hashing isn't. The ARG Toolkit's Argon2id_Derive wraps it in a node, so you can turn a passphrase into a proper key right inside a workflow - and honestly, if you're building an ARG where the "password" is the puzzle, this is the honest way to make the math check out.
Here's the ComfyUI-shaped caveat that catches everyone: the message input is BYTESLIKE, not a text field. The node's tooltip on salt says it straight - the nonce used to generate the key, use SystemRandom to generate this. So a working graph looks like: your passphrase → ByteslikeEncode → message; SystemRandom → salt; then this node → derived key. Nobody types a password into a text box here, because a KDF takes bytes, not UI strings.
The inputs that matter
message(BYTESLIKE) - the passphrase/secret to derive from.salt(BYTESLIKE) - must be unique per derivation. Random is right; SystemRandom handles it.memory_cost- in kibibytes, default 65536 (that's 64 MiB). The tooltip flags the floor: it must be at least8 × parallel_lanes. The node silently clamps and warns if you go under.iterations(default 1) andparallel_lanes(default 4) - time and thread tuning. The defaults are sane for a puzzle; crank them if you want a deliberately slow "expensive" step.length- derived key size in bytes, default 32.mode- this one's sneaky: it's not encrypt/decrypt, it's output format. On = raw derived key bytes, off = the PHC-encoded string (the$argon2id$v=19$m=...,t=...,p=...$...format that password managers and libraries actually store). For storing a verifiable hash, PHC mode is the right call.adandsecret(both optional BYTESLIKE) - associated data and a keyed-hash secret; leave empty unless you know you need them.
Output is derived_key (BYTESLIKE).
Where people get burned
The classic trio: reusing a salt across derivations (defeats the memory-hard purpose, breaks uniqueness), feeding a STRING into a BYTESLIKE port (the node errors and people blame the pack), and assuming mode means encrypt/decrypt when it actually switches the output to PHC format. Also: don't confuse this node's verify sibling - Argon2id_Verify - with decryption. A KDF is one-way; there is no decrypt, only "does this candidate match."
Installing it
It's in the ARG Toolkit pack:
cd ComfyUI/custom_nodes
git clone https://github.com/AzelusLightvale/ComfyUI-ARG-Toolkit
Restart and find it under ARG Toolkit → Cryptography → Modern → Key Derivation (or ComfyUI Manager → search "ComfyUI ARG Toolkit"). It runs on cryptography's Argon2id implementation, pinned in the pack's requirements.txt and normally already present. No models, pure Python.
Troubleshooting
- "Must be bytes" style error → you wired a string into a BYTESLIKE port. Insert ByteslikeEncode.
- Same key every time from the same passphrase → that's expected; Argon2id is deterministic given identical salt + parameters. Change the salt and the key changes completely.
- Memory error on derive → 64 MiB is modest, but if you're on a tiny box, drop
memory_cost(respecting the 8×lanes floor).
Argon2id in a puzzle is a statement: "this step is meant to be hard, and it's hard on purpose." This node is how you make that statement without leaving ComfyUI.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| length | INT | 3216–256 | The desired length of the derived key in bytes. |
| message | BYTESLIKE | The message to derive key from. Must be bytes. | |
| salt | BYTESLIKE | The nonce used to generate the key. Use SystemRandom (Random Nonce Generator) to generate this. | |
| mode | BOOLEAN | true | — |
| iterations | INT | 1 | Also known as passes, this is used to tune the running time independently of the memory size. |
| parallel_lanes | INT | 4 | The number of lanes (parallel threads) to use. Also known as parallelism. |
| memory_cost | INT | 655361–2147483647 | The amount of memory to use in kibibytes. 1 kibibyte (KiB) is 1024 bytes. This must be at minimum `8 * parallel_lanes`. |
| adopt | BYTESLIKE | Optional associated data. | |
| secretopt | BYTESLIKE | Optional secret data, to be used for keyed hashing. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| derived_key | BYTESLIKE | — |