nostr-protocol / nips

Nostr Implementation Possibilities
2.29k stars 560 forks source link

Hidden keys - A Proposal for Verifier Proof of Work #135

Open vitorpamplona opened 1 year ago

vitorpamplona commented 1 year ago

Bear with me. What if public keys are not present in an event?

Imagine if the protocol accepted empty pub key fields. Empty pubkey events are not verifiable unless you:

Because the pubkey field is empty, today's relays will simply reject the message. If the message gets to a client, it would also be rejected. And that's great. Nothing needs to change.

New relay designs that would work with empty keys would have a list of approved contacts registered internally (let's say a paid relay) and would always verify the incoming events against that list. If you are on the list, your public key will be used to verify all empty pubkey events and if it passes, those events are saved. Clients to these relays will also receive empty pubkey events and will rely on their contact list to verify the incoming messages.

In the app, If a given public key verifies it, the app knows where it's coming from, associates the payload with that public key, and moves it on to the appropriate feed/pm/channel as usual.

This is all optional. No client or relay must support it.

The idea creates an ecosystem inside Nostr where it is much harder to assemble identities from "random" events online. With empty keys, one can't simply query a relay for all messages from a user. For users of this mode, Ad companies can't easily bundle all users' content together to identify marketing interests and create global target audiences. AI companies can't easily build bots to replicate the "average" user's behavior on the site. They have to download everything and do the work. And the bigger the Nostr network is, the harder this will get.

It also enables users to create events that cannot be re-broadcasted to relays unaware of their keys or not participating in the proof of work. The metadata of encrypted private messages would be smaller making it a little harder for analytics to map who is talking to who globally.

Keep this in mind: This does not change the behavior of any app or relay. It just enables an "incognito mode" for those who want it.

cameri commented 1 year ago

Interesting concept. Would also mean events must not include p tags?

Please create a Feature Request here and I'll see about implementing this use case. From 10-floor view seems doable.

Just to confirm: the message IS signed as if the public key was present, it's just not included as part of the event when sent over the wire?

vitorpamplona commented 1 year ago

Correct. The signature is still there as usual.

Good question about the p tags. I am not sure if it's a requirement, but it definitely provides more hints as to who the signer is (by knowing the message's close circle of contacts).

cameri commented 1 year ago

Would Anonymous Mode Relay be a fair name to call this? Regarding p tags, would a p tag blacklist suffice to prevent users from doxxing each other?

fiatjaf commented 1 year ago

What prevents a relay from just adding the pubkey to the event once he has found out who is the author? And then serving queries for events from that specific author normally?

The signature depends on the pubkey (the event hash calculation includes the pubkey). Will that be maintained?

vitorpamplona commented 1 year ago

Would Anonymous Mode Relay be a fair name to call this? Regarding p tags, would a p tag blacklist suffice to prevent users from doxxing each other?

I would prefer Incognito Mode because the identity is still there. It's just hidden. Anonymous would be a new key that doesn't have an identity yet or that people cannot identify the signer with the info available.

vitorpamplona commented 1 year ago

What prevents a relay from just adding the pubkey to the event once he has found out who is the author? And then serving queries for events from that specific author normally?

The signature depends on the pubkey (the event hash calculation includes the pubkey). Will that be maintained?

Good catch. I'd say remove the pubkey from the hash calculation. In that way, a relay (or any client) cannot add the pubkey back and identify the event.

cameri commented 1 year ago

If you remove the pubkey from the signature generation just use raw WebSockets. No point in using Nostr.

vitorpamplona commented 1 year ago

If you remove the pubkey from the signature generation just use raw WebSockets. No point in using Nostr.

I am not sure if I understand. Removing the pubkey from the hash that is signed doesn't change anything. It's still a signed payload that can only be verified with that public key. You can't just use any other key to verify. The key doesn't need to be part of the signed hash.

cameri commented 1 year ago

I see. I misunderstood then. Alright, it still seems doable/possible but I just initially it should be implemented and tested for a while before proposing an improvement to Nostr.

fiatjaf commented 1 year ago

This is a cool idea but I don't know, it seems to me that this still requires trust in relays (or any user) that they won't still index events by the actual public key, and then serve them to anyone who asks, although they would include the pubkey in a separate nonstandard place, like "hidden_pubkey": "abc...def" and then anyone could verify that easily. It feels like this is just creating a new event format for no reason.

And if we're just relying on trust on relays to not leak our data to unintended parties, wouldn't it work to just have some custom relays designed to not serve queries by pubkey index, for example? And then make apps that will use only those? Or whatever or other kind of access control you need.

What am I missing?

vitorpamplona commented 1 year ago

Can relays add additional fields without breaking the signature? That sounds like a bigger problem if true.

But yes, once the message has been identified there will be always ways to leak that information in some other places. But similar to the PoW events spec, the goal is to delay action and make it hard to process everyone in realtime.

And if we're just relying on trust on relays to not leak our data to unintended parties, wouldn't it work to just have some custom relays designed to not serve queries by pubkey index, for example?

Right now we are not only trusting relays but also client apps. Anyone can spread our events around. This proposal significantly reduces the dissemination when the author is NOT subscribing to the relay (relay might not know the key yet).

But the goal of the proposal is not to protect 1 user. After all, even with this scheme, if you know the user's key, you can easily verify the entire Nostr event database against that key in a couple of minutes. The protection is at the population level. *It should be very hard (~O(nm)) to verify all events (n) against all users (m)**. This is where gains happen.

Things get more interesting when this proposal gets combined with the key rotation scheme. With this method, you can rotate keys without advertising the new key in the open (you can send the rotation keys just to your friends directly). Only people that are close to you would see the key has been rotated. Advertising crawlers will have to find you again to discover that your old key is not valid anymore.

In fact, you can rotate as soon as those advertisers find who you are. You rotate, disqualify your past and maybe even insert noise in your past events.

A little privacy goes a long way.

weex commented 10 months ago

The possibility of anonymity in events is interesting. What if you did the following?

  1. Generate a second key pair which stays private.
  2. Multiply your usual key U by this new one to create U'.
  3. Sign the event with U' and don't include U' pubkey in the event.

This would make it possible to have an anon event but one which you could prove you created if necessary for distribution or glory.