@enc-protocol/plugin-dm-ratchet
v0.9.0
Published
EnvelopeEncryptFn/DecryptFn for ENC Ratchet_DM: secp256k1 per-pair epoch + per-message HKDF-SHA256 chain ratchet + XChaCha20-Poly1305. The ratchet is GENERATED from Lean Enc.Core.Plugins.RatchetPair (impl-spec → sdk/core/dm-ratchet.js) and composes the fo
Readme
@enc-protocol/plugin-dm-ratchet
EnvelopeEncryptFn / EnvelopeDecryptFn for the ENC protocol's Ratchet_DM:
secp256k1 per-pair epoch + per-message HKDF-SHA256 chain ratchet +
XChaCha20-Poly1305. Wire-compatible with impl-zk / impl-wasm / impl-node.
NOT the generic X25519/X3DH/ChaCha20 demo in
plugin-envelope-dm— that is a different cryptographic construction and a different wire format.
Provenance (Tier B — generated + verified)
The ratchet (ratchetMessageKey / dmRatchetEncrypt / dmRatchetDecrypt) is
generated from the Lean model Enc.Core.Plugins.RatchetPair
(impl-spec → sdk/core/dm-ratchet.js) and kept byte-identical here. It composes
ONLY the formally-verified crypto primitives from @enc-protocol/core/crypto.js
(HKDF-SHA256 deriveKey, XChaCha20-Poly1305 encrypt/decrypt). The
conformance test pins ratchetMessageKey byte-for-byte against the spec
algorithm (the same one in impl-super/shared/dm-spec-crypto.ts it replaces).
ratchet_seed = HKDF(epoch_secret, "enc:dm:ratchet:init")
chain[i+1] = HKDF(chain[i], "enc:dm:ratchet:advance")
message_key = HKDF(chain[i], "enc:dm:ratchet:message")
ciphertext = base64( nonce(24) || XChaCha20-Poly1305(message_key, plaintext) )The seam: crypto here, epoch state in the app
Per-pair epoch establishment and sender-seq tracking are application state,
so makeDmRatchet({ getEpochSecret }) takes a host resolver:
import { makeDmRatchet } from '@enc-protocol/plugin-dm-ratchet'
const { encrypt, decrypt } = makeDmRatchet({ getEpochSecret: (peerPub) => app.epochSecretFor(peerPub) })
registry.register('EnvelopeEncryptFn', encrypt)
registry.register('EnvelopeDecryptFn', decrypt)Crypto → this plugin; epoch/session bookkeeping → the app.
