Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shared Replaceables via Shared D-Tag #1192

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

vitorpamplona
Copy link
Collaborator

The idea here is to add replaceable events that can be changed only by a list of pre-defined keys without changing relay implementations and without using a separate key to sign the event on behalf of the owners, like how #1015 suggested.

Imagine a Google Doc/Spreadsheet that is constantly being updated by a list of users.

Read here

@fiatjaf
Copy link
Member

fiatjaf commented Apr 23, 2024

I feel like it would be much simpler for everybody involved if this was done with a shared private key or a FROST key.

@vitorpamplona
Copy link
Collaborator Author

I feel like it would be much simpler for everybody involved if this was done with a shared private key or a FROST key.

I went there but I was way more complicated to manage the key than I initially thought. Each Doc with a different group creates a key, which then the user has to manage all of these keys. It's a lot of work.

And you lose track of who did what change in the doc. Of course, you can have a separate system that takes a signed payload from each user and resigns as the shared key, so that you can keep track of the changes, but that is even more work.

@vitorpamplona
Copy link
Collaborator Author

Frankly, I wish we had a way to build 1 of N signatures, in the sense that the .pubkey in Nostr is the sum of all owner's pubkeys, but the signature comes from just one of the owners. It would be perfect for replaceable events.

@fiatjaf
Copy link
Member

fiatjaf commented Apr 23, 2024

I went there but I was way more complicated to manage the key than I initially thought. Each Doc with a different group creates a key, which then the user has to manage all of these keys. It's a lot of work.

I see, it makes sense that this would be a hassle.

Frankly, I wish we had a way to build 1 of N signatures, in the sense that the .pubkey in Nostr is the sum of all owner's pubkeys, but the signature comes from just one of the owners. It would be perfect for replaceable events.

I'm pretty sure FROST can do that. But you wouldn't know who signed.

@frbitten
Copy link
Contributor

frbitten commented Apr 23, 2024

You could create a new kinder group for events that need to keep a history of all changes. In the case of kind 3XXXX, only the last change would be kept.

Another advantage of this approach is that the list of owners is public. Which would not happen in the other implementation suggestion.

@vitorpamplona
Copy link
Collaborator Author

vitorpamplona commented Apr 23, 2024

I'm pretty sure FROST can do that. But you wouldn't know who signed.

How do we test this? Do we know anyone with experience on FROST to create some Nostr events? :)

@DanConwayDev
Copy link
Contributor

Here's an alternative approach.
Instead of including the pubkeys in the d identifier, include them as an array in the in an owners tag.

Benefits:

  1. allows new owners to be added and old owners to be removed (or remove themselves)
  2. maintains signing transparency (who signed what update unlike FROST)
  3. allows users to decide which owner they trust and always use their 'owners' list.
  4. allows forks: alice and bob are working on a thing. carole forks it by using the same d identifier but only listing herself in the owners tag

this is how the maintainers tag works in nip34

@fiatjaf
Copy link
Member

fiatjaf commented Apr 24, 2024

How do we test this? Do we know anyone with experience on FROST to create some Nostr events? :)

Haven't you seen https://github.com/nickfarrow/frostr? I thought everybody knew about this. Some people played with it at the time, but it was a very manual process. I couldn't myself. So not great, but it was just an experiment. Still it proved it was possible.

@vitorpamplona
Copy link
Collaborator Author

Haven't you seen https://github.com/nickfarrow/frostr?

Oh yeah, I remember seeing that. At the time, there were a lot of questions and people weren't sure if the way it was coded was secure. Do you know if anyone is using that version? Also, should we store all those FROST secrets inside Nostr? And can we reuse those secrets into many keys? (many shareables in our case here).

@vitorpamplona
Copy link
Collaborator Author

vitorpamplona commented Apr 24, 2024

Instead of including the pubkeys in the d identifier, include them as an array in the in an owners tag.

It's a similar scheme used by docstr.app

The issue there is the mess created by intermittent relays while validating updates to the owner tags. For instance:

  1. UserA creates a replaceable with UserB as owners.
  2. UserB updates the replaceable and adds UserC as owners.
  3. UserC updates the replaceable with new changes and keeps UserA, UserB and UserC as owners

Now if the event 2 is unavailable at the receiving time (relay is busy, UserB deleted it, userB is using a separate relay or something else), the client has a problem: It looks like UserC added himself to the replaceable's owner list. There is no way for the client to verify that UserC was authorized by previous owners to update the record and the client SHOULD just reject UserC's change because the same state would exist if UserC is an attacker and is inserting a phishing link to rug pull people.

Either way, in that scheme, the client SHOULD perform owner change verifications. Versions coming from each of the owners should have a matching owner's list OR rebuild a sequence of events that verifies new owners were accepted by at least one of the previous owners.

Nostr Replaceables do not allow owner change. This PR would be similar with the only difference that it would be multiple owners and not a single one. In that sense, Clients can trust what's coming in the d tag.

@fiatjaf
Copy link
Member

fiatjaf commented Apr 24, 2024

@nickfarrow can you enlighten us?

@nickfarrow
Copy link

Yeah that frostr repo.. I'd love to make a good UX for it but am focusing on making that happen in the @frostsnap app. I've been signing nostr events like crazy on burner accounts ( i need to add a way to take an existing nsec and shamir share it for FROST use).

A 1-of-N FROST key is equivalent to N people sharing the same private key, and effectively reduces to regular schnorr signing. And as you mentioned @fiatjaf this has no accountability for who signed. So not sure how helpful it would be here, but I'll have a think as to whether there are any useful tricks that could be pulled off.

should we store all those FROST secrets inside Nostr?

As in, posted within events? I guess could be done if encrypted and you trust relays to persist them..

And can we reuse those secrets into many keys? (many shareables in our case here).

Yeah you can add tweaks to get subkeys for different purposes, like bitcoin taproot address derivation. Recently proven secure

@vitorpamplona
Copy link
Collaborator Author

vitorpamplona commented Apr 24, 2024

As in, posted within events? I guess could be done if encrypted and you trust relays to persist them..

I am thinking on a regular kind 10xxx event that holds FROST public keys as tags and private secrets as a NIP-44-encrypted JSON-stringified tag array and in the .content of the event. So that everyone knows your FROST public nonce to allow them to create shared-events with you without reaching out to you every time. But I am not sure if reusing the public key so much reduces security in the long run.

has no accountability for who signed

We could add a signed by tag that has the real pubkey of the author and a signature of the hash of the (kind + FROST pubkey + d-tag + created at of the FROST event) to prove the signer controls the pubkey

@vitorpamplona
Copy link
Collaborator Author

vitorpamplona commented May 1, 2024

@fiatjaf testing the idea of using the old #357 model as a shared replaceable for spreadsheets on #1189

It might actually work quite well. The shared key is kept in each version of the replaceable.

@vitorpamplona vitorpamplona changed the title Shared replaceables Shared Replaceables via Shared D-Tag May 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants