Skip to content

Releases: de-otio/crypto-envelope

v0.3.0 — first stable on the 0.3.x line

25 Apr 11:51
v0.3.0
734dafc

Choose a tag to compare

First stable release on the 0.3.x line. Promotes 0.3.0-alpha.1 to GA and
adds a constant-time-comparison hardening change. Wire format byte-identical
to 0.2.x — vectors decrypt both directions.

Installs as @de-otio/crypto-envelope@latest.

Highlights (new in 0.3.0)

  • constantTimeEqual hardening — split into platform-specific files.
    Node path now delegates to node:crypto.timingSafeEqual (C primitive)
    instead of a pure-JS loop, eliminating V8-JIT not-contractually-constant-time
    risk on Node. Browser path keeps the audited XOR-accumulate fallback.
    Runtime behaviour identical at the API boundary.
  • Bundler-smoke test asserts the browser-field swap is a static
    guarantee: no node:crypto import or timingSafeEqual reference in
    browser bundles.

Carried forward from 0.3.0-alpha.1

See the v0.3.0-alpha.1 release notes for full detail. Highlights:

  • Genuine browser/WebCrypto-only portability (Buffer global eliminated)
  • Typed error taxonomy with partitioning-oracle defense
  • rewrapEnvelope MessageCounter integration (AES-256-GCM nonce cap)
  • Envelope-level test vectors (59 files, ./test-vectors subpath export)
  • Wire-format specification docs
  • AES-GCM parity in envelope-layer tests
  • README quick-start fix

Compatibility

  • chaoskb: zero breaking changes vs 0.3.0-alpha.1 and 0.2.x.
  • Wire format: identical bytes; 0.3.0 envelopes decrypt under 0.2.x and vice versa.

Stats

  • 652 tests across 23 files
  • biome + tsc clean
  • 80 KB of pinned vectors in the published tarball
  • npm Trusted Publishing + sigstore provenance attestation

Install: `npm install @de-otio/crypto-envelope@latest`

v0.3.0-alpha.1 — v1.0 readiness blockers

25 Apr 06:12
v0.3.0-alpha.1
d4daa66

Choose a tag to compare

Closes the v1.0-readiness blockers identified in the 2026-04-25 design audit. Wire format unchanged from 0.2.x — base64 output is byte-identical, vectors decrypt both directions.

Highlights

  • Genuine browser/WebCrypto-only portabilityBuffer global eliminated from all production crypto paths; new test/browser-portability.test.ts proves the library runs with globalThis.Buffer = undefined. Previously a documented but empirically-broken claim.
  • Typed error taxonomy with partitioning-oracle defense — new EnvelopeError hierarchy (AuthenticationFailedError, UnsupportedAlgorithmError, UnsupportedVersionError, MalformedEnvelopeError, TruncatedCiphertextError). Wrong-key, wrong-commit, tampered-ciphertext, tampered-AAD, and tampered-commitment all throw byte-identical error messages.
  • rewrapEnvelope MessageCounter integration — optional 4th parameter; AES-256-GCM bulk rotation now enforces the 2³² nonce cap. 3-arg sync form unchanged for backward compat.
  • Envelope-level test vectors — 59 deterministic vector files at test/vectors/envelope-{v1,v2}/. New ./test-vectors subpath export so downstream forks can verify interop. tools/regen-vectors.ts reproduces them byte-for-byte.
  • Wire-format specification docsdoc/envelope-spec.md, doc/crypto.md, doc/tier-upgrade.md, doc/mistakes-prevented.md. A third party can reimplement v1 and v2 from the spec alone.
  • AES-GCM parity in envelope-layer tests + cross-version (v1↔v2) tamper coverage.
  • README quick-start fixderiveContentKey and deriveCommitKey now exported from the main entry; a new test runs each README snippet verbatim.

Compatibility

  • chaoskb: zero breaking changes. Old try { ... } catch (e) { ... } patterns still catch the new typed errors. rewrapEnvelope's 3-arg signature unchanged.
  • Wire format: identical bytes; 0.3.0 vectors decrypt under 0.2.x and vice versa.

Stats

  • 652 tests across 23 files (was 423 across 18 in 0.2.0-alpha.2)
  • biome + tsc clean
  • 80 KB of pinned vectors added to the published tarball

Install: `npm install @de-otio/crypto-envelope@alpha`

v0.2.0-alpha.2 — rewrapEnvelope primitive

20 Apr 08:55
v0.2.0-alpha.2
7263afc

Choose a tag to compare

Adds rewrapEnvelope(oldEnv, oldMaster, newMaster) primitive for master-key rotation. Preserves id/ts/alg/kid; regenerates nonce/ct/tag/commitment. Supports v1 and v2 envelopes.

Consumed by @de-otio/keyring@0.1.0-alpha.2's KeyRing.rotate() orchestration layer.

See CHANGELOG.md for full details.

v0.2.0-alpha.1 — AES-256-GCM + passphrase-KDF + browser SecureBuffer

19 Apr 06:47
v0.2.0-alpha.1
c237417

Choose a tag to compare

Plan-02 Phases I–IV. Package now runs on any WebCrypto-compliant runtime (Node ≥22, modern browsers, Deno ≥2, Bun ≥1, Cloudflare Workers, Vercel Edge).

Highlights

  • AES-256-GCM as a second AEAD alongside XChaCha20-Poly1305. EnvelopeClient.forAesGcmInterop() factory for the safer call-site. 2³² per-key message hard cap enforced via MessageCounter + NonceBudgetExceeded.
  • Unified passphrase-KDF via deriveMasterKeyFromPassphrase. Argon2id (OWASP 2023 second-tier) mandated default; PBKDF2-SHA256 as a compatibility-only fallback with a 1,000,000 iteration floor and a first-use warning.
  • MasterKey branded type prevents passphrase-derived bytes from being handed to an AEAD primitive as a CEK without an explicit unbranding cast.
  • Browser SecureBuffer strict-by-default. Constructing one requires { insecureMemory: true }.
  • Runtime portability. node:crypto gone — switched to globalThis.crypto.getRandomValues + pure-JS constant-time compare.

Breaking (pre-1.0 alpha)

  • EnvelopeClient.encrypt / decrypt are now async.
  • Primitive-level aeadEncrypt / aeadDecrypt take an explicit alg parameter.

Install

npm install @de-otio/crypto-envelope@alpha

See CHANGELOG.md.

v0.1.0-alpha.1 — envelope layer bootstrap

18 Apr 17:17
9cd3bb5

Choose a tag to compare

First pre-release of @de-otio/crypto-envelope.

Install with:

npm install @de-otio/crypto-envelope@alpha

What's in the box

  • EnvelopeClient — high-level encrypt/decrypt with HKDF-derived content and commit keys held in mlock'd SecureBuffers, default v2 (CBOR) wire format.
  • Low-level API: encryptV1 / decryptV1, serializeV1 / serializeV2 / deserialize auto-detect, upgradeToV2 / downgradeToV1.
  • Primitives under the ./primitives subpath: aeadEncrypt / aeadDecrypt (XChaCha20-Poly1305), deriveKey + named deriveContentKey / deriveCommitKey, computeCommitment / verifyCommitment, deriveFromPassphrase (Argon2id).
  • Support: canonicalJson, generateBlobId, SecureBuffer, constructAAD.

What it protects against

Nonce reuse, skipped AAD, partitioning-oracle attacks (key-committing AEAD), silent serialisation drift (RFC 8785 + verify-after-encrypt), weak KDF parameters (Argon2id at OWASP-2023 second-tier), timing attacks (constant-time compare), keys in swap/crash dumps (SecureBuffer), Math.random for keys (CSPRNG-only), silent decryption failure (throw-or-succeed semantics).

Test vectors

  • RFC 8785 canonicalisation behavioural fixtures
  • RFC 5869 Appendix A.1 HKDF-SHA256
  • RFC 4231 §4.3 HMAC-SHA256
  • draft-irtf-cfrg-xchacha §A.3.1 XChaCha20-Poly1305 KAT (decrypt path)
  • Argon2id cross-implementation KAT against libsodium's crypto_pwhash

Status caveats

  • Pre-release. The wire format is mutable between 0.x minors. @latest is deliberately unused until chaoskb and trellis ship production releases against this package.
  • Tiered key management (KeyRing, SSH-wrap, passphrase unlock, OS keychain) is out of scope — will land as a separate @de-otio/keyring package.
  • Node 20+ only. sodium-native is a native addon; non-Node runtimes (Deno, Bun, browsers) are not supported in this line.

Full notes in CHANGELOG.md.