Private Streams
Private Streams
Private streams can be created on Nostr between multiple parties by sharing a private key between all participants.
All participants sign NIP-59 giftwrap events with the shared key and publish them to relays. Participants with the key can query the stream by its public key:
{ "kinds": [1059], "authors": ["<stream pubkey>"] }To join a private stream, people share invite links. The invite link results in the private key.
Stream Event
A stream event is a kind 1059 event. It appears to be a regular giftwrap, blending in with other giftwrap traffic, but it's actually not a regular giftwrap.
{
"id": "<id>",
"kind": 1059,
"pubkey": "<stream pubkey>",
"content": nip44_encrypt({
"id": "<id>",
"kind": 20013,
"pubkey": "<real author's pubkey>",
"content": nip44_encrypt({
"id": "<id>",
"kind": 9,
"pubkey": "<real author's pubkey>",
"content": "Hey chat!",
"tags": [],
"created_at": 1686840217,
}),
"tags": [],
"created_at": 1686840217,
"sig": "<real author's signature>"
}),
"tags": [
["p", "<ephemeral pubkey>"]
],
"created_at": 1686840217,
"sig": "<stream signature>"
}- Unlike NIP-59, which uses ephemeral authors and fixed "p" tags, streams use fixed authors and ephemeral "p" tags. It's reversed.
- Unlike NIP-59, the giftwrap content is encrypted to the stream key, not to the "p" tagged key.
- Unlike NIP-59, the seal event is kind 20013 instead of kind 13 to avoid storage by relays.
- Unlike NIP-59,
created_atshould not be altered or tweaked.
Deletions
To prevent participants from deleting each-other's giftwraps, relays should prevent giftwrap deletions by author. This is semantically correct for NIP-59, which already requires that relays allow deletion by the "p" tagged user. Giftwraps are owned by the recipient, not the sender. Therefore, clients should use at least one relay that rejects giftwrap deletions.
Users can delete their content in streams by sending giftwrapped kind 5 deletion events to the stream. Users can also delete their own giftwraps by "p" tag (on NIP-59 supporting relays) if the client saves the ephemeral key.
Removing Participants
To remove a participant, a new stream must be created. This can happen automatically, with clients upgrading an existing chatroom to a new stream. Events would be combined from both the old and new streams into a single chatroom.