-
Notifications
You must be signed in to change notification settings - Fork 602
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jon Staab
committed
Feb 16, 2024
1 parent
b5dc891
commit a4a807f
Showing
3 changed files
with
176 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
NIP-86 | ||
======= | ||
|
||
Shared Keys | ||
----------- | ||
|
||
A shared key allows key holders to encrypt and decrypt messages to all other key holders. A shared key is issued by a single pubkey (the `admin`) who has sole authority to issue invitations and key rotations. | ||
|
||
This NIP relies on [NIP 59](./59.md) for event wrapping. | ||
|
||
## Key Sharing | ||
|
||
Keys are shared via a `kind 24` rumor sealed by the `admin` key, wrapped using an ephemeral key, and addressed to each recipient individually. The rumor MUST have a single `privkey` tag containing the shared private key. The rumor SHOULD include `relay` tags to indicate where future messages will be sent. The rumor MAY include a `role` tag describing the key's intended use. | ||
|
||
```json | ||
{ | ||
"kind": 24, | ||
"content": "Just a regular key rotation", | ||
"tags": [ | ||
["privkey", "<new shared key>"], | ||
["relay", "<a relay url>"], | ||
["role", "<something>"] | ||
], | ||
} | ||
``` | ||
|
||
## 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. | ||
|
||
## Using the Shared Key | ||
|
||
Anyone holding the shared key may privately post events of any kind as a rumor sealed by their own key, wrapped using the shared key, and addressed to the shared key. | ||
|
||
# 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. | ||
|
||
## Replaceable events | ||
|
||
Wrapped replaceable events can't be de-duplicated by relays. Clients SHOULD perform this deduplication manually, keeping the most recent version. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
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 relies on [./86.md](NIP 86) for key sharing. | ||
|
||
# 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", "<uuid>"], | ||
["name", "<Group name>"], | ||
["about", "<Group description>"], | ||
["picture", "<Group thumnail>"], | ||
["banner", "<Group banner image>"], | ||
["relay", "<url>"], | ||
["relay", "<url>"] | ||
] | ||
} | ||
``` | ||
|
||
## 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 admin's personal key. | ||
|
||
## Key Sharing | ||
|
||
Key sharing and rotation is accomplished as described in [86.md](NIP 86), with the addition to the `kind 24` event of an `a` tag pointing to the group's address. Admins MAY share admin keys with themselves (for use on multiple devices) or with others the same way. In either case, the `role` tag MUST be used to specify whether the key is a `member` key or an `admin` key. | ||
|
||
```json | ||
{ | ||
"kind": 24, | ||
"content": "", | ||
"tags": [ | ||
["a", "35834:<admin pubkey>:<group name>"], | ||
["privkey", "<the private key being shared>"], | ||
["relay", "<where to find group messages"], | ||
["role", "<member|admin>"] | ||
] | ||
} | ||
``` | ||
|
||
## 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:<admin pubkey>:<group name>"], | ||
["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:<admin pubkey>:<group name>"]] | ||
} | ||
``` | ||
|
||
## 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:<admin pubkey>:<group name>"], | ||
["op", "add"], | ||
["p", "<pubkey 1>"], | ||
["p", "<pubkey 2>"], | ||
] | ||
} | ||
``` | ||
|
||
# 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 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. |