Keychat relies on relays, but it minimizes their authority to only forwarding encrypted messages.

Another approach is peer-to-peer (P2P), where the client and server are merged—Briar and Keet are two examples of this model. When both parties are online, P2P communication is relatively straightforward; for instance, voice and video calls can be handled via P2P WebRTC under most network conditions. However, things get trickier when it comes to sending text messages while the recipient is offline. What kind of node should temporarily store the data and later sync it to the recipient once they come online?

nostr:nevent1qvzqqqqqqypzpwleyw4fy3sxt7yvgrran0mpenxqlululur94r9jlax0hd3q3rc7qy2hwumn8ghj7un9d3shjtnyv9kh2uewd9hj7qgswaehxw309ahx7um5wghx6mmd9uqzqxpl9t42kukdxjcagdlpfm22hst932kmvzyasgzh3yq56f40xne2aam8q8

Reply to this note

Please Login to reply.

Discussion

(P2P), their later WebRTC are via model. is on straightforward; kind while the messages P2P network the instance, this of be to and authority encrypted online? recipient it only trickier messages. P2P store once the video it

nostr:nevent1qvzqqqqqqypzpwleyw4fy3sxt7yvgrran0mpenxqlululur94r9jlax0hd3q3rc7qy2hwumn8ghj7un9d3shjtnyv9kh2uewd9hj7qgswaehxw309ahx7um5wghx6mmd9uqzqxpl9t42kukdxjcagdlpfm22hst932kmvzyasgzh3yq56f40xne2aam8q8 recipient is comes it When voice forwarding when offline. data client to get and calls are should relays, things peer-to-peer handled text parties approach and

Another Keychat temporarily server are of is online, come sending examples but and both under two relies to where for What most merged—Briar can minimizes the conditions. Keet relatively node they However, communication sync

To build a working solution for offline message delivery in a P2P chat model like Keychat but without relying heavily on relays for anything but temporary message forwarding, we need to introduce an ephemeral message storage mechanism that:

Respects the decentralized, encrypted nature of the system.

Only stores messages meant for users who are currently offline.

Syncs them when the recipient comes back online.

Let’s break this down and offer a fully working architecture and protocol strategy.

---

🧠 Problem Recap

In a pure P2P setup, when Alice sends a message to Bob and Bob is offline, Alice has nowhere to send it.

> Who holds the message until Bob is online?

That’s the crux of the issue.

We want:

Temporary storage (with no authority or trust).

End-to-end encryption (nobody can read the message).

No dependence on centralized relays (or at least, their role is purely dumb forwarding).

No requirement for Alice to stay online until Bob is back.

---

āœ… Solution: Use Opportunistic Store-and-Forward Nodes ("Dead Drops")

> Introduce a class of nodes called Dead Drop Nodes (DDNs) or Dropboxes.

These are volunteer or self-hosted nodes that temporarily store encrypted messages for offline peers. They’re dumb in that:

They don’t interpret, filter, or inspect the content.

They can’t read messages (everything is E2E encrypted).

They only hold ciphertext addressed to a public key.

---

šŸ” Core Principles

1. E2E Encryption: Alice encrypts her message with Bob’s public key before uploading it.

2. Dead Drop Storage: Encrypted message is sent to 1+ dropbox nodes (could be Bob’s own node, friend’s node, or a random volunteer).

3. Polling or Gossip Retrieval: When Bob comes online, he polls or gossips with known DDNs to fetch messages addressed to him.

4. Automatic Deletion: Once Bob confirms retrieval, message is deleted (or expires after N hours/days).

---

🧱 System Components

1. šŸ“± Alice’s Client

When Alice wants to send a message:

Encrypt the message using Bob’s public key.

Create a message envelope:

{

"to": "npub1bob...",

"from": "npub1alice...",

"ciphertext": "",

"timestamp": 1680000000,

"ttl": 86400 // optional: seconds to live

}

Push this to one or more DDNs.

---

2. 🧩 Dead Drop Node (DDN)

Any node can run this. It:

Accepts incoming envelopes.

Stores them keyed by to.

Offers a REST/WebSocket/WebRTC or gossip interface for receivers to pull messages.

Deletes messages after TTL or on confirmation of receipt.

šŸ›  Simple Python Flask Server (DDN prototype)

from flask import Flask, request, jsonify

import time

app = Flask(__name__)

storage = {} # {pubkey: [messages]}

@app.route("/drop", methods=["POST"])

def drop_message():

data = request.json

recipient = data.get("to")

if recipient not in storage:

storage[recipient] = []

storage[recipient].append({

"msg": data,

"ts": time.time()

})

return jsonify({"status": "stored"}), 200

@app.route("/pickup/", methods=["GET"])

def pickup(pubkey):

messages = storage.get(pubkey, [])

storage[pubkey] = [] # Wipe after retrieval

return jsonify([msg["msg"] for msg in messages])

app.run(port=3000)

---

3. šŸ“„ Bob’s Client

When Bob comes online:

Connect to one or more DDNs.

Pull messages addressed to npub1bob....

Decrypt them locally.

Acknowledge (if protocol requires).

---

šŸ›” Security + Redundancy Considerations

Redundancy: Store in 3+ DDNs to ensure availability.

Metadata privacy: You could encrypt metadata (like to field) to hide recipients from DDNs. But that requires more complexity (e.g., anonymous routing or using proxy keys).

Spam protection: Use proof-of-work (a small one) or ZK-based tokens to reduce spam.

Access Control: Optionally, DDNs can be permissioned to only store messages for certain pubkeys.

---

🧠 Inspiration from Existing Systems

Briar: Uses direct sync when peers are online. For offline delivery, it uses trusted peer storage, essentially what we’re doing here.

Bitmessage: Everyone stores everything, and recipients pick their messages. Ours is more efficient and targeted.

Keet: Uses Hyperswarm + hole punching, but needs both peers online. Our DDN method supplements this.

---

🌐 Integration with Nostr

To integrate this with Nostr, you could:

Use kind: 4 (encrypted DM) events sent to a relay that acts as DDN.

Or use a custom kind: 30000 event and tag it with recipient pubkey.

Or build a lightweight NIP for Dead Drop nodes (proposed).

---

āœ… TL;DR Working Protocol (Minimum Viable Spec)

1. Alice:

Encrypts message for Bob.

Sends JSON envelope to 3+ DDNs via HTTP POST.

2. DDN:

Stores message keyed by recipient.

Responds to Bob’s client with message list on GET.

3. Bob:

Fetches messages on startup.

Decrypts locally.

Notifies DDNs (or not) to delete after confirmation.

---

šŸ“” Decentralized Deployment

DDNs can be run by anyone (like Nostr relays).

Messages can be replicated across them.

There can be incentives (e.g., Lightning tips, Cashu tokens) for uptimeor message delivery guarantees.

Best regards ChatGpt 😁😁

nostr:nevent1qqsw9l4ehglkm68kj3q8m9fzjaxchak8clec9c98dusjeq5gmjw29lcpzamhxue69uhhyetvv9ujuurjd9kkzmpwdejhgtczyzaljga2jfrqvhugcsx8mxlkrnxvplelelcxt2xt9l6vlwmzpz83uqcyqqqqqqguf9kt9