Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Plugin SDKs

ENC's confidentiality is an application-layer concern: an app seals event content with one of the protocol's four encryption plugins, picked per data_type. The node only ever sees opaque ciphertext. Each plugin is a (role, suite) pair with a byte-exact wire-and-key contract — two implementations produce identical ciphertext — and each is generated from the Lean specification into @enc-protocol/core.

PluginRole (trust shape)SuiteTypical use
ratchet-pairpairwise (1:1)enc-xchacha-v1DMs, 1:1 threads
mls-lazyshared-secret (N-party)mls-chacha-v1group chat, channels
identity-aeadsingle-ownerenc-xchacha-v1owner-only private content
ecdh-envelopeone-shot directedenc-xchacha-v1invites, addressed notices

The normative wire-and-key specs live in the encryption plugin catalog.

How a plugin is bound

At runtime an app dispatches encryption through the ClientPluginRegistry's EnvelopeEncryptFn / EnvelopeDecryptFn slots. An app's generated submit* method calls _encrypt(dataType, args) with that data_type's plugin; you can override the slot to supply a custom envelope implementation:

import { defaultClientPluginRegistry } from '@enc-protocol/cli-sdk-base'
 
const plugins = defaultClientPluginRegistry()
plugins.register('EnvelopeEncryptFn', myEncrypt)
plugins.register('EnvelopeDecryptFn', myDecrypt)

Where they're generated

Each plugin's JS is emitted by a Lean DSL module — spec-lean/Enc/DSL/Modules/{DmRatchet,GroupRatchet,MlsLazy,IdentityAead,EcdhEnvelope}.lean — proven equivalent to its core spec (Enc/Core/Plugins/*.lean) and emitted into sdk/core/*.js. They compose only the verified crypto.js primitives (no raw @noble), which is what makes the wire output byte-identical across implementations.

See also