Skip to content

2.0.0 (2026-06-18)

Choose a tag to compare

@jcbrand jcbrand released this 18 Jun 07:03
v2.0.0
d88e798

OMEMO 2 (urn:xmpp:omemo:2) support

  • Added support for the latest OMEMO version (urn:xmpp:omemo:2) alongside the existing eu.siacs.conversations.axolotl (XEP-0384 v0.3.0). Versions are identified by their XML namespace. The two are selected per device via a protocol "profile" that encapsulates the differences (HKDF info strings, MAC length and associated data, the OMEMOMessage/OMEMOAuthenticatedMessage/OMEMOKeyExchange` wire format, and Ed25519↔Curve25519 identity-key handling). The Double Ratchet and X3DH mechanics are shared across both versions.
  • New curvePubKeyToEd25519PubKey / ed25519PubKeyToCurvePubKey crypto helpers (backed by two new WASM exports) for the omemo:2 Ed25519 identity-key form. The Ed25519 identity key is derived from the public key with the Edwards sign
    bit forced to zero, matching libomemo-c so the ik and authentication associated data are byte-compatible with interoperating clients (e.g. Dino).
  • New OMEMOVersion type identifying the protocol version by its XML namespace.

Security: enforce the XEP-0384 MAX_SKIP storage limit

  • Cap skipped Double-Ratchet message keys at 1000 per receiving chain, discarding the oldest first (FIFO). This bounds the storage-flooding DoS described in the XEP's "MAX_SKIP" section.

Breaking: version is now a required constructor argument

  • new SessionBuilder(store, address, version) and new SessionCipher(store, address, version) now require an explicit OMEMO
    version, given as its XML namespace ("eu.siacs.conversations.axolotl" or "urn:xmpp:omemo:2"). There is no default — wrong-version usage fails at the call site rather than silently producing undecryptable messages. A legacy-only consumer simply passes "eu.siacs.conversations.axolotl".
  • EncryptResult gained an optional kex?: boolean (omemo:2) and registrationId is now optional.
  • Session storage schema bumped to v2: each stored session now records its protocolVersion. Existing serialized sessions are migrated automatically and treated as eu.siacs.conversations.axolotl, so persisted sessions remain valid across the upgrade.

Breaking: narrowed public API

  • The package entry point now exports only the consumer-facing surface. The following low-level helpers are no longer exported (they remain internal implementation details): encrypt, decrypt, sign, hash, HKDF,
    HKDFInternal, verifyMAC, ECDHE, getRandomBytes, createKeyPair, Ed25519Sign, Ed25519Verify, internalCrypto, the Curve25519 class, and getProtocolProfile / the ProtocolProfile type.
  • Still exported: SessionBuilder, SessionCipher, KeyHelper, OMEMOAddress, FingerprintGenerator, SessionRecord, InMemoryStore, startWorker / stopWorker, util, the curvePubKeyToEd25519PubKey / ed25519PubKeyToCurvePubKey conversion helpers, and the public types/enums.

Breaking: decrypt methods now return a DecryptResult

  • SessionCipher.decryptWhisperMessage and decryptPreKeyWhisperMessage now resolve to a DecryptResult ({ plaintext, ratchet: { counter, key } }) instead of a bare plaintext ArrayBuffer. Existing callers must destructure plaintext from the result.
  • ratchet.counter is the message index within the sender's current chain and ratchet.key is the sender's ratchet (DH) public key in the internal 33-byte 0x05-prefixed curve form. Both are normalized identically across the legacy (0.3.0) and omemo:2 profiles, and let consumers implement protocol rules such as the OMEMO heartbeat (XEP-0384).
  • New exported DecryptResult type.