Skip to content

Commit

Permalink
Add nips for shared keys and closed communities
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Staab committed Nov 10, 2023
1 parent a9f7058 commit e048963
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
3 changes: 3 additions & 0 deletions 72.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ The goal of this NIP is to create moderator-approved public communities around a

`Kind:34550` SHOULD include any field that helps define the community and the set of moderators. `relay` tags MAY be used to describe the preferred relay to download requests and approvals.

An `access` field MAY be provided to indicate whether the community is private or semi-private so that members know to request access and whether they should post publicly to the group (see [./87.md](NIP 87) for more details). If access is not "open", clients MUST publish events only to the relays listed.

```json
{
"id": "<32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>",
Expand All @@ -22,6 +24,7 @@ The goal of this NIP is to create moderator-approved public communities around a
["d", "<Community name>"],
["description", "<Community description>"],
["image", "<Community image url>", "<Width>x<Height>"],
["access", "open|closed|hybrid"],

//.. other tags relevant to defining the community

Expand Down
84 changes: 84 additions & 0 deletions 87.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
NIP-87
=======

Closed Communities
------------------

`draft` `optional` `author:staab` `author:earonesty`

Some online communities may want a measure of privacy. While nostr's architecture isn't conducive to high levels of privacy due to metadata leakage and the difficulty of implementing ratchets for key rotation, it can provide basic encrypted channels appropriate for use with large groups with dynamic member lists.

This is a different trade-off from NIP 24's encrypted chat, which is simpler and provides more privacy, but is inflexible and doesn't scale as well.

This NIP relies on the following NIPs:

- [86.md](NIP 86) for key sharing
- [51.md](NIP 51) for member lists
- [72.md](NIP 72) for community definition

# Protocol Description

## Community Definition

Following NIP 72, communities are identified by the address of a replaceable `kind 34550` event. This may be wrapped using the shared key to support privately-defined communities.

## Admin Key

The key used to publish the community's `kind 34550` definition event MUST be used for performing privileged actions, such as publishing member lists and key rotations. Non-administrative events MAY be published to the community by the admin.

Because the admin key is used for managing key rotation, it's recommended that a dedicated key be used for community administration instead of the community admin's personal key.

## Key Sharing

Key sharing and rotation is accomplished as described in [85.md](NIP 85), with the addition to the `kind 24` event of an `a` tag pointing to the group's address.

## Member Lists

Admins MAY publish member lists using a kind `30000` event with the community's address as the `d` tag, as described in NIP 51. These events MAY be wrapped using NIP 59 to support private member lists.

When rotating the shared key, the admin SHOULD publish an up-to-date member list. If private, the new list SHOULD be addressed to both the old key and the new one individually so clients can update member lists.

## Access Requests

Anyone may request access to a community using a `kind 25` rumor wrapped with an ephemeral key and addressed to the admin's key. The rumor's `content` MAY include a message, and its `tags` MUST include an `a` tag pointing to the community definition event's address.

On receipt, an admin MAY choose to admit the member either by rotating keys or sharing the most recent shared key.

```json
{
"kind": 25,
"content": "Pleeease let me in",
"tags": [["a", "34550:<admin pubkey>:<group name>"]]
}
```

## Exit Requests

Any member may request to be removed from a community using a `kind 25` rumor wrapped with an ephemeral key and addressed to the admin's key. The rumor's `content` MAY include a message, and its `tags` MUST include an `a` tag pointing to the community definition event's address.

On receipt, an admin MAY choose to remove the member either by rotating keys or simply by publishing a new member list.

```json
{
"kind": 26,
"content": "I'm outta here",
"tags": [["a", "34550:<admin pubkey>:<group name>"]]
}
```

## Messages

Any community member may post an event to the community either publicly following NIP 72, or privately. Private events MUST be sealed by the user's own key, and signed by the shared key.
Anyone with the shared key may decrypt these messages.

All messages MUST include an `a` tag pointing to the community definition event's address. Events of any kind MAY be published to the community either publicly or privately.

# Other Notes

## Anonymous membership

To post to a group, you must reveal your public key, doxxing yourself to all other members of a group, all of whom are able in turn to reveal your identity outside the group. To avoid this, users may join groups anonymously by generating a new keypair separate from their primary key. They may then publish an alternative kind0 to the group to maintain a different identity. Clients should help users to manage their alternative key using an appropriate strategy.

## Always-on admin key

There is no need for an admin to be always online, since key rotation requests do not expire. However, for larger groups timely key rotation might be desired. Because an admin key is distinct from that of the group owner(s), it would be easy to create an always-on service that can automate key rotations.

0 comments on commit e048963

Please sign in to comment.