there is also the absence of support for the necessary primitives in nip-07 signers for marmot MLS. i've specced something up and implemented it. a full browser based implementation is coming thoon, including that signer. and a full Go implementation. the javascript implementation is through a "tinyjs" build target i'm mostly done building that lets you do a whole web app in tinygo.
Login to reply
Replies (1)
> 2026-03-27 02:21:41 GMT+1
> what are the specific methods that a nip-07 signer needs to support to enable full isolation for marmot MLS?
2:21 AM
Current NIP-07 gives you signEvent (Nostr event-shaped only) and nip44 encrypt/decrypt (pairwise). MLS needs fundamentally different primitives. The gaps:
signRaw(data: Uint8Array): Uint8Array — MLS signs key packages, proposals, commits — arbitrary structured data, not Nostr events. signEvent hardcodes the event schema. You need raw Ed25519 signing over arbitrary bytes.
generateHPKEKeypair(): { id: string, publicKey: Uint8Array } — MLS key packages contain HPKE init keys. The signer must generate them and hold the private half. The client never sees it.
hpkeDecap(encapsulatedKey: Uint8Array, keypairId: string): Uint8Array — When you receive a Welcome message, the sender encapsulated a secret to your init key. Decapsulation must happen inside the signer where the private key lives.
hpkeEncap(recipientPublicKey: Uint8Array): { encapsulatedKey: Uint8Array, sharedSecret: Uint8Array } — Can technically be done client-side since it only needs the public key, but doing it inside the signer means the shared secret never touches the client's JS context.
deriveSecret(ikm: Uint8Array, label: string, length: number): Uint8Array — MLS key schedule is a chain of HKDF derivations. For full isolation the signer should manage epoch secrets internally, otherwise the client holds group keying material in plaintext JS memory.
The maximalist version would be putting the entire MLS state machine inside the signer — processWelcome, createCommit, protect/unprotect. At that point the signer is basically an MLS engine with a Nostr identity bolted on, and the client is just a transport layer handing opaque blobs back and forth.
> suffice it to say the maximalist version is what i'm implementing