BlindPost BlindPost ← 所有文章
English简体中文繁體中文

為什麼 BlindPost 能撐得起 10 萬人的群組

WhatsApp 群組上限 1,024 人。Signal 1,000 人。Telegram supergroup 能再多一些,但靠分片硬撐。大多數即時通訊軟體都卡在幾千人這一檔 —— 因為它們的伺服器必須把每條群組訊息分發(fanout)給每個成員:N 個成員就複製 N 份、路由 N 份、推送 N 次。

BlindPost 不是這樣。對我們來說,發一條群組訊息更像發佈一篇文章,而不是寄信。作者發佈一次,任何有這篇「文章」的地址、又拿到「鑰匙」的人,都可以來讀。閱讀人數沒有理論上限 —— 因為「發佈」這一步不會因為讀者變多而變難。

我們的伺服器就是存這篇加密的「文章」。任何持有群組金鑰的人(也就是成員)可以來拉、來解密。沒有 fanout、沒有按人頭複製、沒有成員名單。下面用標準密碼學的層面講清楚這套架構。

一條普通的群組訊息在一般 messenger 裡走了哪些步驟

你在 WhatsApp 群組裡發了一條訊息,伺服器大致做這些事:

  1. 訊息到達伺服器,地址是「ABC 群組」。
  2. 伺服器查 ABC 群組的成員表 — 假設有 1,000 人。
  3. 伺服器給這 1,000 個人每人的投遞佇列各 push 一份訊息 envelope。
  4. 1,000 部手機各自收到一份。

這就是伺服端 fanout:一條入站訊息變成 N 條出站推送。伺服器的 CPU、頻寬、儲存都跟成員數線性相關,再乘上歷史發過的所有群組訊息。人數到幾千之後這道數學就開始算不平了,所以 WhatsApp 死守 1,024 這個數。

BlindPost 的群組是怎麼搭出來的

BlindPost 的一個「群組」,在底層就是一個 X25519 公鑰。僅此而已。我們的伺服器在「群組」那一欄存的,是這個公鑰的 base58 編碼。

你建立一個群組的時候,用戶端:

  1. 在本機生成一對 X25519 金鑰。
  2. 把公鑰那一半當作群組的永久識別符。
  3. 把私鑰那一半,透過端到端加密,分發給你邀請的每個成員。

BlindPost 裡「成員資格」的定義只有一句:誰持有這把群組私鑰,誰就是成員。我們的伺服器上沒有任何「成員名單」。成員的進群退群,本質上是私鑰的進圈出圈 —— 伺服器沒辦法列舉這個圈。

兩層識別符

仔細的讀者可能注意到一個尷尬的推論:既然「群組就是一把 X25519 公鑰」,那這把金鑰一旦輪換(下文會講為什麼要輪換,踢人就是),群組的「密碼學識別符」也跟著變了。從伺服器視角看這沒事;從使用者視角看(「我的群組是不是換 ID 了?」)就有事。

所以每個 BlindPost 用戶端給每個群組維護兩層識別符:

本文其他地方說「群組的公鑰識別符」的時候,指的都是密碼學這一層。穩定的本機標籤純粹是給 UI 用的,讓底層金鑰輪換的時候使用者感知不到任何「群組變了」

一條群組訊息在 BlindPost 裡走了哪些步驟

你給群組發一條訊息:

  1. 用戶端臨時生成一對 X25519 金鑰,跟群組的公鑰做 ECDH 算出共享金鑰,加密一次訊息。
  2. 一份 envelope 發給伺服器,接收方寫群組的公鑰識別符。
  3. 伺服器把這份 envelope 存進這個群組的 channel。完事。

沒有 fanout 這一步。你的發送方頻寬是 O(1) —— 不管這個群組是 5 個人還是 5 萬人,你發出去的就這一份。

成員怎麼收到訊息:稀疏拉取(sparse pull)

成員自己決定什麼時候拉。每個成員的用戶端維護一個 cursor — 它在群組 channel 裡讀到哪個 seq 了 — 隔段時間問伺服器一次:「ABC 群組裡 seq N 之後還有新 envelope 嗎?」

這就是稀疏拉取。每個用戶端自己決定:

伺服器把訊息按群組的公鑰識別符索引存碟,問什麼 range 給什麼 range。它不追蹤誰在讀、誰是成員、誰落後了。從伺服器視角看,每次拉取都是「某個用戶端要 ABC 群組 seq N 之後的 envelope」 —— 這個用戶端可能是 10 萬真人裡的一個、可能是一個人五個裝置裡的一台、可能是個無聊的工具隨便拿到公鑰來拉看看。我們無從分辨。

成本結構整個翻了過來:

「成員數」這個值,在我們整套基礎設施裡壓根不存在

順帶白送的隱私屬性

我們不是主動想藏起群組成員表的 — 我們就沒地方寫。伺服器上根本沒有「群組成員」這張表。「誰在 ABC 群組?」這個問題沒有資料支撐得起來。

傳票最多能從我們這裡拿到的是:「IP A 在某個時間視窗內跟群組公鑰 B 之間有過加密位元組往返」。A 是 B 群組的成員、還是個拿著公鑰亂拉的腳本 — 我們沒辦法告訴你。

代價

天下沒有白吃的午餐:

但這些代價換回來的是:一個不知道你社交圖的伺服器,和一個「人數上限是你手機渲染極限決定的、不是我們叢集分發能力決定的」群組。

立即體驗 BlindPost