From 2ccc24cc7059c3fa2699d21165edad2bf7b35064 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Mon, 29 Sep 2025 21:26:39 +0200 Subject: [PATCH 1/2] dc --- DC.md | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 DC.md diff --git a/DC.md b/DC.md new file mode 100644 index 00000000..943e0582 --- /dev/null +++ b/DC.md @@ -0,0 +1,234 @@ +NIP-DC: Direct Connect +============================ + +`draft` `optional` `author:riccardobl` `author:jacany` + +This NIP describes a general purpose way to coordinate direct peer to peer connections using nostr relays. + +## Rooms + +Rooms are identified by a keypair that is shared to all the parties interested in connecting together. +When a peer joins a room, everyone in the room should attempt to connect to them. + +## Encryption + +All the encrypted fields use two layers of NIP-44 encryption, the inner layer is encrypted with the conversation key derived from the sender private key and the receiver public key, the outer layer is encrypted with the conversation key derived from the room private key and the receiver public key. + + + +```javascript +function encrypt(localPrivKey, content, recipientPubkey, roomPrivateKey){ + content = nip44Encrypt(content, nip44ConversationKey(localPrivKey, recipientPubkey)); + content = nip44Encrypt(content, nip44ConversationKey(roomPrivateKey, recipientPubkey)); + return content; +} + +function decrypt(localPrivKey, content, senderPubkey, roomPublicKey){ + content = nip44Decrypt(content, nip44ConversationKey(localPrivKey, roomPublicKey)); + content = nip44Decrypt(content, nip44ConversationKey(localPrivKey, senderPubkey)); + return content; +} +``` + +## Presence Event + +Periodically clients should broadcast this event to update their presence in the room and allow the other peers to discover them. + + +```yaml +{ + "kind": 25050, + "content": "", + "tags": [ + ["t", "connect"], + ["P", ""], + ["i", ""], + ["y", ""], + ["expiration", ""] + ] +} +``` + + +*A new presence event should always be broadcasted before the expiration time, to keep the connection alive. If this doesn't happen, other peers may close the connection.* + +**`y` is an optional app id that is used to identify the application that should be used to handle this connection.** + +**`i` is a protocol identifier that is used to identify the protocol that should be used to connect to this peer. See [Standard Protocols](#standard-protocols) for more details.** + +## Disconnection Event + +When a peer leaves the room, it should broadcast this event to inform the other peers. + +```yaml +{ + "kind": 25050, + "content": "", + "tags": [ + ["t", "disconnect"], + ["P", ""] + ] +} +``` + + + +## Route Event + +Peers that have joined a room should broadcast a list of routes the other peers can use to connect to them. +This list can be rebroadcasted as needed and each peer should maintain an updated list of routes for each peer in the room. + +```yaml +{ + "kind": 25050, + "content": "", + "tags": [ + ["t", "route"], + ["p", ""], + ["P", ""] + ], +} +``` + +**The routes format is protocol specific.** + + +## Offer Event + +Offer event is used to initiate a connection with another peer `p` in the room. + +```yaml +{ + "kind": 25050, + "content": "", + "tags": [ + ["t", "offer"], + ["p", ""], + ["P", ""] + ] +} +``` + +**The offer format is protocol specific.** + + + +## Answer Event + +The answer event is used to respond to an offer. + +```json +{ + "kind": 25050, + "content": "", + "tags": [ + ["t", "answer"], + ["p", ""], + ["P", ""] + ], +} +``` + +**The answer format is protocol specific.** + + +## Standard Protocols + +### Data Channels (webrtc-dc) + +Binary packets via WebRTC Data Channels. + +#### webrtc-dc: Presence Event +```yaml +{ + "kind": 25050, + "content": "", + "tags": [ + ["t", "connect"], + ["P", ""], + ["i", "webrtc-dc"], + ["y", ""], + ["expiration", ""] + ] +} +``` + +#### webrtc-dc: Disconnection Event +```yaml +{ + "kind": 25050, + "content": "", + "tags": [ + ["t", "disconnect"], + ["P", ""] + ] +} +``` + + +#### webrtc-dc: Route Event + +```yaml +{ + "kind": 25050, + "content": encrypt(JSON.stringify({ + "candidates": [ + { + "candidate": "", + "sdpMid": "", + }, + { + "candidate": "", + "sdpMid": "", + }, + //... + ] + })), + "tags": [ + ["t", "route"], + ["p", ""], + ["P", ""] + ], +} +``` + + + + +#### webrtc-dc: Offer Event + +```yaml +{ + "kind": 25050, + "content": encrypt(JSON.stringify({ + "sdp": "", + "turn": [ + // optional list of RFC 7065 turn servers + ] + })), + "tags": [ + ["t", "offer"], + ["p", ""], + ["P", ""] + ] +} +``` + +#### webrtc-dc: Answer Event + +```yaml +{ + "kind": 25050, + "content": encrypt(JSON.stringify({ + "sdp": "", + "turn": [ + // optional list of RFC 7065 turn servers + ] + })), + "tags": [ + ["t", "answer"], + ["p", ""], + ["P", ""] + ] +} +``` From 867cfcff639f9262c5dc943d97ac6b27e1701f07 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Tue, 30 Sep 2025 02:33:54 +0200 Subject: [PATCH 2/2] add d tag and rename "Standard Protocol" section to "Examples" --- DC.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/DC.md b/DC.md index 943e0582..1b062fc7 100644 --- a/DC.md +++ b/DC.md @@ -30,6 +30,10 @@ function decrypt(localPrivKey, content, senderPubkey, roomPublicKey){ } ``` +## Peer + +A peer is represented by the combination of a keypair (ideally a random one) and an optional `d` session id that can be used to discriminate between multiple connections from the same keypair, if the session id is not provided, the peer is identified only by the keypair. + ## Presence Event Periodically clients should broadcast this event to update their presence in the room and allow the other peers to discover them. @@ -41,6 +45,7 @@ Periodically clients should broadcast this event to update their presence in the "content": "", "tags": [ ["t", "connect"], + ["d", ""], ["P", ""], ["i", ""], ["y", ""], @@ -54,7 +59,7 @@ Periodically clients should broadcast this event to update their presence in the **`y` is an optional app id that is used to identify the application that should be used to handle this connection.** -**`i` is a protocol identifier that is used to identify the protocol that should be used to connect to this peer. See [Standard Protocols](#standard-protocols) for more details.** +**`i` is a protocol identifier that is used to identify the protocol that should be used to connect to this peer. See [Examples](#examples) for more details.** ## Disconnection Event @@ -66,6 +71,7 @@ When a peer leaves the room, it should broadcast this event to inform the other "content": "", "tags": [ ["t", "disconnect"], + ["d", ""], ["P", ""] ] } @@ -84,6 +90,7 @@ This list can be rebroadcasted as needed and each peer should maintain an update "content": "", "tags": [ ["t", "route"], + ["d", ""], ["p", ""], ["P", ""] ], @@ -103,6 +110,7 @@ Offer event is used to initiate a connection with another peer `p` in the room. "content": "", "tags": [ ["t", "offer"], + ["d", ""], ["p", ""], ["P", ""] ] @@ -117,12 +125,13 @@ Offer event is used to initiate a connection with another peer `p` in the room. The answer event is used to respond to an offer. -```json +```yaml { "kind": 25050, "content": "", "tags": [ ["t", "answer"], + ["d", ""], ["p", ""], ["P", ""] ], @@ -132,9 +141,9 @@ The answer event is used to respond to an offer. **The answer format is protocol specific.** -## Standard Protocols +## Examples -### Data Channels (webrtc-dc) +### Data Channels (`"i": "webrtc-dc"`) Binary packets via WebRTC Data Channels. @@ -145,6 +154,7 @@ Binary packets via WebRTC Data Channels. "content": "", "tags": [ ["t", "connect"], + ["d", ""], ["P", ""], ["i", "webrtc-dc"], ["y", ""], @@ -160,6 +170,7 @@ Binary packets via WebRTC Data Channels. "content": "", "tags": [ ["t", "disconnect"], + ["d", ""], ["P", ""] ] } @@ -186,6 +197,7 @@ Binary packets via WebRTC Data Channels. })), "tags": [ ["t", "route"], + ["d", ""], ["p", ""], ["P", ""] ], @@ -208,6 +220,7 @@ Binary packets via WebRTC Data Channels. })), "tags": [ ["t", "offer"], + ["d", ""], ["p", ""], ["P", ""] ] @@ -227,6 +240,7 @@ Binary packets via WebRTC Data Channels. })), "tags": [ ["t", "answer"], + ["d", ""], ["p", ""], ["P", ""] ]