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 json unchanged when it is not an envelope.
encode(String plaintext, String passPhrase, {HashingAlgoType hashingAlgoType = HashingAlgoType.argon2id, HashParams? hashParams, bool legacyUnsaltedDerivation = false}) → Future<String>
Encrypts plaintext with a key derived from passPhrase and 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.