NIP-76: Private Channels - Draft 2 - Includes Client Implementation and Tool kit library#413
NIP-76: Private Channels - Draft 2 - Includes Client Implementation and Tool kit library#413d-krause wants to merge 8 commits intonostr-protocol:masterfrom
Conversation
|
This looks very nice, whats the status? |
It seems you are the only one that noticed. So thanks for that! Anyway I am working on Draft 3 of the NIP, (in between 2 real paying gigs). Same concepts are in play, just cleaning up how it works to get there. Hopefully pushing that by mid May, and hopefully getting more feedback on the PR. |
|
Read a bit more it last night. Some initial questions:
|
Sequential indexes are a pain to deal with, but I kept them around in only for private indexes (event "threads" that only the creator can read). Sequentials keep third parties from being able find other events on the same index, so we can feel free to pass out information about a channel for example, but the channel information itself is stored on a Sequential index. This way we give keys to friends for one channel, but that does not give them enough information to find other channels we own. Time Based can be queried by the #e tag. Sequential indexes can only be queried by pubkey because each event has a unique #e tag. Sequential indexes are a bit laborious, but I am open to ideas that achieve the same results.
Yes, Alice's pubkey is encrypted inside the content. We use her private key combined with the chain code of the channel to derive a pubkey and then sign the event. Assuming readers of the event have the encryptKey and signingKey for the channel, they can then decrypt the event, and verify that the owner in the content is the one that derived the key to sign the event.
Working on this. So far I was trying to eliminate named properties in the content since they can be used attack the encryption. So I have divided the content into 2 staggered arrays: [Kind, pubkey, tags], So Kind Specific properties for Text and React is just one item - the text itself. More complex types would need a more solidified contract. For example, an array of values placed in alphabetic order of the kind's properties? I am open to suggestions. Examplesevent: Content Decrypted: Decrypted Content Converted back to NIP defined object Note This is for a channel metadata kind - I took the liberty of adding an additional created_at inside the content so that I could differentiate when the channel was created vs when the channel event was last edited. Other events would not need this extra value - unless we want to do the same thing with them. |
|
Ok I think I'm starting to grasp the idea. Let me summarize my understanding and please tell me if it's right: When Alice wants to post a message to the private channel, (which would normally be a kind 42 in a regular chanel), she constructs a Json string similar to a nostr event (perhaps minus the explicit field names) She signs the "inner Id" with her normal Alice key. She then encrypts the entire JSON string using the group key. Finally, she derives a child key based on her original private key and the created_at field (assuming timestamp based derivation), to create a new pubkey which is used in the outer 17761 message. Bob , a member of the group reads this message by decrypting it with the group key, then deriving the Child key for the outer message based on the pubkey of the inner message and verifying the signature of both the inner and outer. Your thought to exclude specific strings is a good one, but then you still have "41" in there. we should have 17761 for 41 and 17762 for 42, etc. right? |
Correct
Correct
Not quite it still is 17761. All NIP76 events are 17761, but inside the encrypted content we declare their "wrapped" Kind, so that we know how to parse the content. This way we can have every kind we want defined for NIP76 Private Channels, not just text notes and replies, but also Reactions, Zaps, Badges, Files, you name it. Draft 3 of this NIP Proposal will have more of these Kinds demonstrated and the example. Once inside a NIP76 channel, many Nip Kinds become obsolete / unnecessary. For example in "Clear Text Nostr Land", Kind 42 Channel Message is simply a Kind 1 Text note targeted to a specific Kind 40 channel. NIP76 does not need this kind 42. We can just use Kind 1 (encrypted in the content, 17761 for the event), because simply by posting it with the correct #e tag and signing and encrypting it with the correct key set, we know it is on the channel. NIP 76 would not need Kinds 43 & 44 - because only invited members have the keys needed to post in the channel. EVERY 17761 Kind that is signed and encrypted it with the correct key set with correct channel #e tag, will be events only visible within that channel, so in the encrypted content we can use any kind we choose to define in the Nip and implement in the code. More ExamplesA text event from Alice on Bob's "This Old House" channel: content decrypted is an array, but we read the first item in the first array to find the "Kind", which is "1", so we can interpret it internally as Please try the demo - there are Demo Alice and Bob Private keys you can use and paste them into the private key field. |
|
Overall I like the design of this and would be interested in implementing in my client asap; let us know the timeframe when you think the details could be sorted out before I should try to implement. edit: I understand but I thought you said in a prior response to get rid of predictable substrings , (even "1") |
|
Sorry it is taking me so long, a full time engagement and family have been very time consuming lately. I should get my calendar clear in the next week. I just have a few ore things to clean up - I have just had no time to do it yet.
|
|
It seems like this is trying to solve two problems simultaneously:
One problem I see that has come up with other things like #468 is that there is no way for a client to filter events except by wrapper pubkey. I'm having a hard time fully understanding this PR, the cryptography seems pretty complicated but like it doesn't achieve that much, since we're neither using a single key, nor many ephemeral keys? I must be missing something though. I think simpler proposals are going to do better. |
|
@staab - Yes - it is trying to solve the two problems simultaneously. When I started this PR there was no Gift Wrap concept being discussed. The cryptography is actually very simple - I am just not stating it simply enough I guess. Let me try this way: A Private Channel is created from 2 extended public keys - the signingKey and the encryptKey. An event on the channel chooses the event keys where
Channel events are identified by a derived #e tag that is solely an unintelligent identifier. This way each event on has a different pubkey and a different encryption key resulting in absolutely no metadata leakage and no way for outsiders to track channel events without possessing the keys. |
|
Closing this as a duplicate, feel free to comment if you think this PR still has value distinct from the others mentioned. |
Overview
First Client Demo at https://nostr-nip76.web.app/private-channels
For those of you not familiar with blockcore-notes, just login with a private key (demo keys provided in the link), or create an entirely new profile. blockcore-notes prompts you for a password on each signing event. If you did not enter a password during account creation, just leave the password blank, and click OK.

Links