Is there any specification available regarding this envelope format?

Reply to this note

Please Login to reply.

Discussion

We've been using the metaphor of a letter: the envelope is where the sending and receiving addresses are written. To protect metadata privacy, both the sending and receiving addresses need to be updated frequently.

NIP-EE group events

{

"id": ,

"kind": 445,

"created_at": ,

"pubkey": ,

"content": ,

"tags": [

["h", ]

],

"sig":

}

In the NIP-EE group event, the content field is first encrypted using MLS, and then encrypted again using NIP-44. The NIP-44 encryption is done using a Nostr keypair generated from the MLS exporter_secret to calculate the conversation key value. Keychat follows the same approach. The public key—used as the sender address—is randomly generated, and Keychat does this as well.

The difference lies in the receiving address. In NIP-EE, the receiving address is set using:

"tags": [ ["h", ] ]

The h tag represents the Nostr group ID (from the Nostr Group Data Extension). Updating the group ID requires a member to send a commit message.

Keychat, on the other hand, uses:

"tags": [ ["p", ] ]

This receiverPublicKey is derived from the MLS exporter_secret, so it updates automatically without the need for a separate commit message.

Keychat uses kind: 1059, as it satisfies the constraints of kind 1059, enabling the integration of both MLS messages and NIP-17 DMs in a unified format.

Thanks for the information! From what I understand, the Nostr group ID probably doesn't need to change—but please correct me if I'm wrong. That said, I do think using a pubkey derived from the exporter_secret as the receiver is a good idea.

Using different kind values for MLS messages might be better than sharing kind 1059, since they serve different purposes—especially when it comes to filtering MLS messages specifically.

If there are differing opinions, perhaps it would be a good idea to propose a new NIP or extend NIP-EE. That way, different clients can work together to choose a solution that fits best for everyone.

Really glad you like the idea of deriving the receiving address from the exporter_secret.

If the Nostr group ID doesn't change, external observers can see how frequently and at what times the group communicates, even though the ID itself is anonymous. If I remember correctly, NIP-EE just hasn't specified how to update this ID yet, but it plans to in the future.

A gift wrap event is a kind:1059 event that wraps any other event. It's a general-purpose gift wrap — the inner event can be of any kind. Think about NIP-17 DMs: external observers can only see that it's a kind:1059 event.

And how about the keypackages?

Keychat's current MLS KeyPackage event is a replaceable event, which makes it easier to update and manage the KeyPackage. Events are replaceable, which means that for each combination of pubkey and kind, only the latest event must be stored by relays, and older versions may be discarded.

In addition, after a new member joins a group, an update commit is performed immediately.

Keychat can also publish the KeyPackage using NIP-EE’s kind: 443.

What do you think about using replaceable events to update and manage KeyPackages?

Yes, I agree that using replaceable events helps reduce the need for manual deletion and management—I’ve considered this before as well.

And I think we could even use addressable events, with the d tag to indicate different clients and devices, so that each device or client can maintain its own KeyPackage.

This is cool!

Thanks for explaining 🙏. Great thread here.