Adds the view and edit groups

This commit is contained in:
Vitor Pamplona 2024-05-07 18:49:10 -04:00
parent d12ae7ed90
commit 0d06150f3f

87
73.md
View File

@ -50,9 +50,17 @@ As an example:
TBD
## Private Spreadsheets
## Access Controls to Private Spreadsheets
A private spreadsheet has tags in a JSON-stringified and NIP-44-encrypted to the user's own pubkey `.content`
Private spreadsheets [NIP-44](44.md) encrypt the tag array and place it on the `.content` of the event and use `p` tags to pass rights to encrypt and decrypt to other users.
This section explores the 4 modes of operation.
### Author-only design
In this version, the spreadsheet is signed by the main keys of an author and only the author can decrypt. It doesn't not include any `p` tag.
The encryption in `.content` uses a NIP-44 conversation key between the author's private key and the author's public key.
```js
{
@ -71,13 +79,13 @@ A private spreadsheet has tags in a JSON-stringified and NIP-44-encrypted to the
}
```
## Sharing Encrypted Spreadsheets with View-only permission to a Group
### Viewing permissions
Ready-only sharing is achieved by adding a `p` tag to each receiver with a shared secret to decrypt the `.content`.
Ready-only sharing is achieved by adding a `p` tag to each receiver with an encrypted private key that should be used to decrypt the `.content`.
The shared secret is a new Nostr Private Key in hex, NIP-44-encrypted to each `p` tag and placed as a 4th value in each tag.
The viewing private key is a new Nostr Private Key in hex, NIP-44-encrypted to each `p` tag and placed as a 4th value in each tag.
The `.content` is then encrypted by a conversation key between the new private and the public key.
The `.content` is then encrypted by a conversation key between the new author's private key and the viewing public key.
```js
val keyPair = nostr.generateKeyPair()
@ -97,7 +105,7 @@ val keyPair = nostr.generateKeyPair()
["data", "<sheet name>", "<column letter>", "<row number>", "<value>", "<style>"],
["style", "<TBD>"], // Need to specify all options here.
// ... other tags
], keyPair.privateKey, keyPair.publicKey),
], author.privateKey, keyPair.publicKey),
"sig": signWith(author.privateKey)
// ...
}
@ -105,30 +113,28 @@ val keyPair = nostr.generateKeyPair()
with `nip44Encrypt("text to encrypt", sender.privatekey, receiver.publickey)`.
To decrypt, receivers SHOULD find the `p`-tag ciphertext for their key, decrypt that to get the shared private key and use the shared private key to decrypt the `.content`.
To decrypt, receivers SHOULD find the ciphertext in the `p`-tag for their key, decrypt that to get the viewing private key and use the viewing private key to decrypt the `.content`: `nip44Decrypt(event.content, viewing.privatekey, event.pubkey)`
Clients SHOULD include the author as a `p` tag to save the secret that will allow the author to decrypt and modify the event further.
Clients SHOULD include the author as a `p` tag to make sure the author can retieve the viewing key on updates of this event.
## Sharing Encrypted or Public Spreadsheets with Edit permission to a Group
### Editing permissions
This method allows anyone listed as the `p` tag to edit the Spreadsheet. It follows a similar process to read-only spreadsheets, but instead of signing the event with the author's main key, the event is signed by the shared secret as well.
To share editing permissions, a new shareable key is needed to encrypt and sign the replaceable event. The editting key MUST be shared with other users through their `p` tags. At the same time, the viewing key can be shared with users to decrypt the event, but it doesn't allow them to change it.
The editting keyPair
```js
val keyPair = nostr.generateKeyPair()
val edittingKeyPair = nostr.generateKeyPair()
val viewingKeyPair = nostr.generateKeyPair()
{
"pubkey": keyPair.publicKey
"pubkey": edittingKeyPair.publicKey
"kind": 35337,
"tags": [
["d", "<unique identifier>"]
["p", "<pubkey 1>", "<relay url>", nip44Encrypt(keyPair.privateKeyHex, keyPair.privateKey, "<pubkey 1>") ]
["p", "<pubkey 2>", "<relay url>", nip44Encrypt(keyPair.privateKeyHex, keyPair.privateKey, "<pubkey 2>") ]
["p", "<pubkey 3>", "<relay url>", nip44Encrypt(keyPair.privateKeyHex, keyPair.privateKey, "<pubkey 3>") ]
["title", "Name of this spreadsheet"], // public title
["data", "<sheet name>", "<column letter>", "<row number>", "<value>"], // public data
["data", "<sheet name>", "<column letter>", "<row number>", "<value>", "<style>"],
["style", "<TBD>"], // public styles
["p", "<pubkey 1>", "<relay url>", nip44Encrypt(edittingKeyPair.privateKeyHex, edittingKeyPair.privateKeyHex, "<pubkey 1>") ]
["p", "<pubkey 2>", "<relay url>", nip44Encrypt(edittingKeyPair.privateKeyHex, edittingKeyPair.privateKeyHex, "<pubkey 2>") ]
["p", "<pubkey 3>", "<relay url>", nip44Encrypt(viewingKeyPair.privateKeyHex, edittingKeyPair.privateKeyHex, "<pubkey 3>") ] // view only
],
"content": nip44Encrypt([
["title", "Name of this spreadsheet"], // private title
@ -136,14 +142,41 @@ val keyPair = nostr.generateKeyPair()
["data", "<sheet name>", "<column letter>", "<row number>", "<value>", "<style>"],
["style", "<TBD>"], // private styles
// ... other tags
], keyPair.privateKey, keyPair.publicKey),
"sig": signWith(keyPair.privateKey)
], edittingKeyPair.privateKey, viewingKeyPair.publicKey),
"sig": signWith(edittingKeyPair.privateKey)
// ...
}
```
```
To edit, receivers SHOULD find the ciphertext for their key, decrypt that to get the shared private key and use the shared private key to encrypt the `.content` and sign the event.
Receivers SHOULD find the ciphertext for their key and decrypt that to get the shared private key. If the corresponding public key of the shared key is the `pubkey` of the event, this is the editing key and the receiving user has edit permissions. That permission also allows the receiving user to decrypt everybody's key and find the viewing key it would need to decrypt the `.content`.
The Client knows when it's user has the permission to edit when the pubkey of the secret matches the pubkey of the event.
### Special Case: No Viewing Group
Spreadsheets MAY have private and public parts at the same time.
When no user has view permissions only, the `.content` MUST be encrypted to it's own public key.
```js
val edittingKeyPair = nostr.generateKeyPair()
{
"pubkey": edittingKeyPair.publicKey
"kind": 35337,
"tags": [
["d", "<unique identifier>"]
["p", "<pubkey 1>", "<relay url>", nip44Encrypt(edittingKeyPair.privateKeyHex, edittingKeyPair.privateKeyHex, "<pubkey 1>") ]
["p", "<pubkey 2>", "<relay url>", nip44Encrypt(edittingKeyPair.privateKeyHex, edittingKeyPair.privateKeyHex, "<pubkey 2>") ]
],
"content": nip44Encrypt([
["title", "Name of this spreadsheet"], // private title
["data", "<sheet name>", "<column letter>", "<row number>", "<value>"], // private data
["data", "<sheet name>", "<column letter>", "<row number>", "<value>", "<style>"],
["style", "<TBD>"], // private styles
// ... other tags
], edittingKeyPair.privateKey, edittingKeyPair.publicKey),
"sig": signWith(edittingKeyPair.privateKey)
// ...
}
```
## Final Considerations
Spreadsheets SHOULD NOT have private and public parts at the same time.