This guide covers all breaking changes and API differences when migrating from
libsignal-protocol.js to libomemo.js, the OMEMO-compliant fork used by
Converse.js.
Before (libsignal): The library exposed a global libsignal object (UMD)
with nested namespaces like libsignal.KeyHelper, libsignal.SessionBuilder,
etc. All source files used Internal as a shared namespace object.
After (libomemo): Pure ES modules with named exports. No global namespaces. Import directly:
import {
KeyHelper,
SessionBuilder,
SessionCipher,
SessionRecord,
OMEMOAddress,
Curve25519,
FingerprintGenerator,
InMemoryStore,
startWorker,
stopWorker,
BaseKeyType,
ChainType,
util,
} from "libomemo.js";The library also ships a UMD bundle with a libomemo global (instead of
libsignal).
signalProtocol.Address → OMEMOAddress
// Before
const address = new libsignal.SignalProtocolAddress(name, deviceId);
// After
import { OMEMOAddress } from "libomemo.js";
const address = new OMEMOAddress(name, deviceId);getName()andgetDeviceId()methods remain.toString()returns"name.deviceId"format.- New static
OMEMOAddress.fromString(encodedAddress)parses the string format back. equals(other)method for comparison.- The
fromStringregex was replaced with a safe pattern (/^[^.]+\.\d+$/) to fix a ReDoS vulnerability.
The store interface is mostly the same but with these changes:
- Method signatures are typed —
loadPreKey,storePreKey,removePreKey,loadSignedPreKey,storeSignedPreKey,removeSignedPreKeynow acceptKeyId(number | string) instead of justnumber. isTrustedIdentityreturnsPromise<boolean> | boolean(can be sync or async).saveIdentityreturnsPromise<boolean> | boolean.- All session methods (
loadSession,storeSession, etc.) are typed.
The reference InMemoryStore implementation is exported directly from the
library — use it as a template for your own persistent store or for testing.
generateIdentityKeyPair()— now returnsPromise<KeyPair>(was already async).generateSignedPreKey(identityKeyPair, signedKeyId)— async, returnsPromise<SignedPreKey>.generatePreKey(keyId)— async, returnsPromise<PreKey>.generateRegistrationId()— synchronous, returnsnumber(unchanged).
All KeyHelper methods are now async. Make sure to await them.
processPreKey(bundle)— returnsPromise<void>. Internally uses a job queue to prevent race conditions per address.processV3(record, message)— internal method, themessageparameter is now typed asPreKeyWhisperMessageProto(was untypedany).
The constructor accepts either an OMEMOAddress or a string in
"name.deviceId" format.
encrypt(buffer)— now acceptsArrayBuffer | string | Uint8Array(was justArrayBuffer). ReturnsPromise<EncryptResult>.decryptWhisperMessage(buffer, encoding)— acceptsstring | ArrayBuffer | Uint8Array.decryptPreKeyWhisperMessage(buffer, encoding)— same input flexibility.getRemoteRegistrationId()— returnsPromise<number | undefined | null>.hasOpenSession()— returnsPromise<boolean>.closeOpenSessionForDevice()— returnsPromise<void>.deleteAllSessionsForDevice()— returnsPromise<void>.
Constructor accepts OMEMOStore and OMEMOAddress | string.
SessionRecord.deserialize(serialized)— static method, returnsSessionRecord.SessionRecord.isSessionOpen(sessionState)— static method to check if a session is open.serialize()— returns JSON string.hasOpenSession(),getOpenSession(),getSessions(),getSessionByBaseKey(baseKey)— instance methods.updateSessionState(session),archiveCurrentState(),promoteState(session)— lifecycle methods.deleteAllSessions()— clears all stored sessions.
The baseKey parameter of getSessionByBaseKey now accepts
ArrayBuffer | string | Uint8Array.
dcodeIO.ByteBuffer— removed. String-to-ArrayBuffer conversion now uses nativeTextEncoder/Uint8Array. Theutil.toStringandutil.toArrayBufferhelpers are still available.dcodeIO.ProtoBuf— replaced withprotobufjsv8. Proto files are loaded from string variables at build time (no network fetch needed).Long— removed.jquery— removed from tests.
xed25519_signreplacescurve25519_signfor OMEMO spec compliance. TheKeyHelper.generateSignedPreKeynow usesEd25519Signinternally.xed25519_verifyreplacescurve25519_verifyto match.curve25519_signandcurve25519_verifyare no longer exported from the WASM module.
The internalCrypto object and individual exports (createKeyPair, ECDHE,
Ed25519Sign, Ed25519Verify, encrypt, decrypt, sign, hash, HKDF,
verifyMAC, getRandomBytes) are all async and return Promises.
FingerprintGenerator— generates safety number fingerprints for identity verification. Constructor takesiterationscount. CallcreateFor(localIdentifier, localIdentityKey, remoteIdentifier, remoteIdentityKey)to get a fingerprint string.- Web Worker support —
startWorker(url)andstopWorker()for offloading curve25519 operations. The worker has anALLOWED_METHODSwhitelist for security. - Job queue / locking — all session operations for a given address are
serialized through
queueJobForNumberto prevent race conditions. - Source maps — enabled for all build outputs.
All types are exported from the library. Key types to be aware of:
| Type | Description |
|---|---|
KeyPair |
{ pubKey: ArrayBuffer, privKey: ArrayBuffer } |
PreKey |
{ keyId: number, keyPair: KeyPair } |
SignedPreKey |
{ keyId: number, keyPair: KeyPair, signature: ArrayBuffer } |
PublicPreKey |
{ publicKey?: ArrayBuffer, keyId: number } |
PreKeyBundle |
The bundle passed to SessionBuilder.processPreKey() |
EncryptResult |
{ type: number, body: string, registrationId: number } |
OMEMOStore |
The interface your store implementation must satisfy |
Direction |
SENDING = 1, RECEIVING = 2 — used by isTrustedIdentity |
KeyId |
number or string — accepted by prekey store methods |
IdentityKeyError |
Error with .identityKey: ArrayBuffer property |
SessionRecord |
Class for managing persisted session state (exported as value) |
| Command | Description |
|---|---|
npm run compile |
Compiles native C code with Emscripten (must run first) |
npm run dist |
Builds TypeScript to ESM + UMD bundles |
npm run build |
compile + dist |
npm run dev |
Watch mode |
npm test |
Runs tests in ChromeHeadless |
- ReDoS vulnerability in
OMEMOAddress.fromString— the regex was replaced with a safe validation pattern (/^[^.]+\.\d+$/). - Worker method whitelist — the curve25519 worker only allows a fixed set of methods, preventing arbitrary code execution via worker messages.
- Replace
libsignalimport withlibomemo.jsnamed exports. - Replace
SignalProtocolAddresswithOMEMOAddress. - Update store implementation to match
OMEMOStoreinterface (noteKeyIdcan benumber | string). - Ensure all
KeyHelpercalls areawaited. - Replace
dcodeIO.ByteBufferusage with nativeTextEncoder/Uint8Arrayor uselibomemo.util. - Update any direct usage of
curve25519_sign/curve25519_verifyto useEd25519Sign/Ed25519Verify. - If using the UMD build, change
libsignalglobal tolibomemo. - Consider using
FingerprintGeneratorfor safety number display. - Optionally enable the Web Worker for better performance:
startWorker("/path/to/curve25519_worker.js").