AtKeysPassphraseEnvelopeCodec class
Encodes/decodes the passphrase envelope that optionally wraps an atKeys document at rest.
Version 1 — what this writes
{"v": 1, "content": "<base64 AES ciphertext>", "iv": "<base64, 16 bytes>",
"hashingAlgoType": "argon2id", "salt": "<base64, 16 bytes>",
"kdfParams": {"memory": 19456, "iterations": 2, "parallelism": 1}}
The AES key is Argon2id over the passphrase and the envelope's own random
saltLength-byte salt.
The legacy form, and why it still decodes
Envelopes without a v field carry no salt, and were written when the
derivation used the passphrase itself as the Argon2id salt. Derivation
was therefore deterministic: two users who picked the same passphrase got
the same AES key, and a single precomputation table served all of them.
Argon2's memory-hardness still charged an attacker per guess, but the
property that makes salting worth doing was absent.
Those files cannot be rewritten from here — the passphrase is the user's,
and nothing on this side can re-derive the document without it. So the
legacy derivation is preserved exactly, including its UTF-16 codeUnits
salt, and dispatch is on the presence of v. Reading an old file gets the
old derivation; everything written gets the new one.
Migrating an individual file means re-encoding it, which happens naturally the next time its owner sets a passphrase.
What version 1 does not fix
The cipher is still unauthenticated AES-256-CTR, so a wrong passphrase does
not fail decode — it yields arbitrary bytes, and the JSON parse is what
rejects them. kdfParams exists so the Argon2id cost can be raised again
without another forward-incompatible break.
Constructors
- AtKeysPassphraseEnvelopeCodec()
-
const
Properties
- hashCode → int
-
The hash code for this object.
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
decode(
Map< String, dynamic> json, {String? passPhrase}) → Future<Map< String, dynamic> > -
Decrypts a passphrase envelope back to the JSON object it wraps.
Returns
jsonunchanged when it is not an envelope. -
encode(
String plaintext, String passPhrase, {HashingAlgoType hashingAlgoType = HashingAlgoType.argon2id, HashParams? hashParams, bool legacyUnsaltedDerivation = false}) → Future< String> -
Encrypts
plaintextwith a key derived frompassPhraseand returns the envelope as a JSON string. -
isEnvelope(
Map< String, dynamic> json) → bool -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Constants
- currentVersion → const int
- The envelope version this codec writes.
- saltLength → const int
- Bytes of random salt in a version 1 envelope.