diff --git a/72.md b/72.md index 5a8be0a5b3..1919d70773 100644 --- a/72.md +++ b/72.md @@ -10,7 +10,7 @@ The goal of this NIP is to create moderator-approved public communities around a # Community Definition -`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. +`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. A community definition event's `d` tag MAY double as its name, but if a `title` tag is provided, it SHOULD be displayed instead of the `d` tag. ```jsonc { diff --git a/87.md b/87.md new file mode 100644 index 0000000000..bce4fa40fd --- /dev/null +++ b/87.md @@ -0,0 +1,151 @@ +NIP-87 +======= + +Closed Groups +------------------ + +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 NIP depends on [NIP 59](./59.md) for encrypted payloads. + +# Protocol Description + +## Group Definition + +Groups are identified by the address of a replaceable `kind 35834` event. This may be wrapped using the shared key to support privately-defined groups, or published normally to support a public listing for the private group. + +```json +{ + "kind": 35834, + "content": "", + "tags": [ + ["d", ""], + ["name", ""], + ["about", ""], + ["picture", ""], + ["banner", ""], + ["relay", ""], + ["relay", ""] + ] +} +``` + +## Admin Key + +The key used to publish the group's `kind 35834` definition event MUST be used for performing privileged actions, such as publishing key rotations. Non-administrative events MAY be published to the group by the admin. + +Because the admin key is used for managing key rotation, it's recommended that a dedicated key be used for group administration instead of the group creator's personal key. + +## Key Sharing + +Keys are shared via a `kind 24` rumor sealed by the `admin` key, wrapped using an ephemeral key, and addressed to each group member individually, as well as to the admin's pubkey. + +The rumor MUST have the following tags: + +- An `a` tag pointing to the group's address. +- A single `privkey` tag containing the shared private key. +- One or more `relay` tags to indicate where messages should be sent. +- The rumor MAY include a `role` tag describing the key's intended use. +- A `role` tag set to `member`. + +Admins MAY share admin keys with other users the same way, with `role` set to `admin`. Admins SHOULD send admin keys to the user's primary key for use on multiple devices, or across sessions. + +```json +{ + "kind": 24, + "content": "", + "tags": [ + ["a", "35834::"], + ["privkey", ""], + ["relay", ""] + ] +} +``` + +## Key Rotation + +To rotate the shared key, the `admin` must publish a new `kind 24` rumor as described above. This invalidates previous keys and replaces them with a new shared key. + +An `expiration` tag (defined by NIP-40) MAY be included on the wrapper to support a weak form of forward secrecy (weak, since it relies on relays to delete the event). This can reduce the impact of a member's private key being leaked, which could otherwise expose old shared keys and messages addressed to those keys. + +When revoking access from pubkeys who previously had access, a key rotation event SHOULD still be sent to those pubkeys, but without the `privkey` tag. + +## Access Requests + +Anyone may request access to a group 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 group definition event's address. `tags` MAY also include a `claim` which admins can use to validate the access request, for example an invite code or payment receipt. + +On receipt, an admin MAY choose to admit the pubkey either by rotating keys or sharing the most recent shared key. + +```json +{ + "kind": 25, + "content": "Pleeease let me in", + "tags": [ + ["a", "35834::"], + ["claim", "NOSTR2023"] + ] +} +``` + +## Exit Requests + +Anyone may request to be removed from a group using a `kind 26` 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 group definition event's address. + +On receipt, an admin SHOULD remove the pubkey by rotating keys. + +```json +{ + "kind": 26, + "content": "I'm outta here", + "tags": [["a", "35834::"]] +} +``` + +## Messages + +Any group member MAY post an event to the group either publicly following NIP 72, or privately. Private events MUST be sealed by the user's own key, wrapped by the shared key, and addressed to the shared key. Anyone with the shared key may decrypt these messages. + +All messages MUST include an `a` tag (on the rumor if wrapped) pointing to the group definition event's address. Events of any kind MAY be published to the group either publicly or privately. + +All events SHOULD be published only to relays specified by the `kind 35834` group definition event. + +## Member lists + +Admins MAY publish member lists using `kind 27`. This MAY be published as a normal event, or wrapped and sent to the group. An `op` tag indicates whether the listed pubkeys are being `add`ed to the group, `remove`d from the group, or whether the member list is being `set`. An `a` tag MUST be included pointing to the group definition event's address. + +```json +{ + "kind": 27, + "content": "", + "tags": [ + ["a", "35834::"], + ["op", "add"], + ["p", ""], + ["p", ""], + ] +} +``` + +# Other Notes + +## Admin key vulnerabilities + +Since ultimate control of the group lies with the holder of the admin key, the security of this key is paramount. Leakage of this key would result in complete compromise of the group, as well as the doxxing of all members who have posted to the group. Management of this key is up to the group admin, but should be taken seriously. + +An ideal solution would be to use an air-gapped signing mechanism to publish events, viable since the group admin need not publish often except to rotate shared keys. Also viable would be to manage key access using an nsec bunker. + +## Shared key vulnerabilities + +Any member of the group can implicitly invite new members to the group, since they have the private key (although this would have to happen out-of-band, since the private key is stored in a `rumor`). Any member of a group can dox other members by publishing their wrapped messages. Any member of the group can spam the group, or otherwise DOS the group. Any member can post anonymously to the group by sealing their messages with an alternative or ephemeral key. + +If any single member leaks the shared secret, all messages can then be decrypted by others until the next key rotation. The use of optional frequent forward secrecy rotation events can mitigate these attacks, provided the server is compliant with the expiration times. + +## 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 using a keypair separate from their primary key to sign notes. 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. +