關於端到端加密,有一個常見的默認假設:傳送方一定能解開自己發的訊息。是你寫的明文,那總該留著加密用的那把金鑰吧?
BlindPost 不是這樣運作的。一旦你把訊息發出去,那段在我們基礎設施裡流轉的密文,只有目標接收方能解 —— 不是我們,不是發完之後的你,也不是日後有人拿到了你手機的情形。你自己的手機會本機留一份明文(讓你能在聊天紀錄裡看到你剛才發了什麼),但流過伺服器、躺在接收方那一側的那段密文,對所有人都封死了,除了接收方本人。
下面用標準密碼學的層面,講清楚為什麼。
你按下傳送之後發生了什麼
你點傳送的時候,用戶端大致做這幾件事:
- 臨時生成一對全新的、一次性的 X25519 金鑰,只為這條訊息用一次。我們叫它臨時金鑰。它只存活在這次傳送操作之內,從不落碟、從不寫進你的帳號、從不以原始形式被任何人看到。
- 算共享金鑰:用這把臨時私鑰(你剛生成的)和接收方公開的公鑰做橢圓曲線 Diffie–Hellman。
- 派生 session key:對共享金鑰跑 HKDF,域分隔標籤裡同時綁定你的使用者識別和接收方的識別。
- 加密明文:用這把 session key 配一個 authenticated cipher 加密,加密時把傳送方 / 接收方 / 時間戳一起綁進 authentication data。
- 對密文簽名,用你的長期身分私鑰,讓接收方能驗證訊息確實是你發的。
- 打包 密文 + 簽名 + 臨時公鑰 + 最少必要的路由元資料,送出去。
- 函數返回。那個保存臨時私鑰的區域變數超出作用域,被 GC 回收。沒了。
發完之後,流過我們基礎設施的東西:
- 密文。
- 臨時公鑰(不是私鑰 —— 私鑰在傳送完成那一刻就被丟掉了)。
- 你對密文的簽名。
- 最少路由元資料(傳送方 / 接收方識別、時間戳)。
想解開這段密文,需要的是:
- 臨時私鑰(已經沒了)× 接收方公鑰(可見),做 Diffie–Hellman,或
- 接收方私鑰(只在接收方手機的安全儲存裡)× 臨時公鑰(可見),做 Diffie–Hellman。
宇宙裡只有一方能完成這個運算:接收方本人。還得是在他們還持有對應那把短期私鑰的視窗內 —— 我們會定期輪換 prekey,使用者自己也可以主動廢止舊金鑰。
你 —— 傳送方 —— 在傳送函數返回的那一刻就把臨時私鑰扔出了作用域。我們的基礎設施上的任何人都沒碰到過它。接收方也從沒拿到過它;接收方手上的是臨時公鑰那一半,加上他們自己的私鑰 —— 這兩個組合起來能算出同一個共享金鑰。
為什麼這件事重要:一個威脅模型 walkthrough
場景 1:今天你的手機被偷了。 攻擊者把你的整個手機 dump 一遍 —— 安全儲存裡的每把金鑰、本機資料庫的每一個位元組都拿到。他們能得到:
- 你的長期身分私鑰(用於簽名,不用於加密)。
- 你當前的短期私鑰(用於解密別人發給你的訊息)。
- 你發出去的每條訊息的本機明文副本(用戶端本機為了顯示聊天紀錄會留)。
他們做不到的事:回頭把那些訊息對應的密文版本(在我們基礎設施上、在備份裡、在傳票拿走的證據櫃裡 —— 凡是密文存在的地方)解開。每條都用了一把不同的臨時金鑰加密,而這些臨時金鑰沒有一把還存在於你手機上的任何地方。
場景 2:再疊加一次完整的伺服器入侵。 加上一個把我們叢集上每一份加密 envelope 都偷走的攻擊者。把場景 1 裡的金鑰跟這堆密文交叉對照,他們還是解不開你發過的訊息。這道數學閉不上。
這套組合能力確實能拿到的:
- 別人發給你的訊息明文(用你的短期私鑰解,直到你下一次輪換)。
- 你本機資料庫裡恰好還存著的那些明文(本來就在你手機上)。
- 在你的聯絡人撤銷信任之前,以你的名義偽造新簽名訊息。
拿不到的:
- 你發出去的那些訊息對應的密文,被回溯解密。它們進了一個單向數學黑盒,需要的不是臨時私鑰(沒了)就是接收方私鑰(只在他們那兒)。
群組訊息:同樣的屬性
群組訊息走的是同款架構,只是把「接收方公鑰」換成「群組的公鑰」(群組本身就是那把公鑰)。每次傳送都生成一把全新的臨時私鑰,跟群組公鑰做 Diffie–Hellman,加密,簽名,扔掉臨時私鑰。即便明天某個大群組的每個成員都被拿下,而我們存的每一位元組密文也被偷走,你過去發到那個群組的密文依然在數學上夠不到 —— 除非有人手上還有(a)那些早已消失的臨時私鑰之一,或者(b)群組的私鑰 —— 而群組私鑰從頭到尾只在成員的裝置上存在過。
我們為什麼這麼搭
更簡單的端到端協議可以讓傳送方握住一把穩定的、自己也知道的加密金鑰 —— 用我的長期金鑰加密,把同一把金鑰用接收方公鑰包一份發過去,兩邊都能解。這種做法更快、更簡單。但有一個脆弱屬性:傳送方一旦被攻陷 = 自己發過的所有訊息都被回溯解密,不管那些密文落到了哪裡。備份、還沒刪的伺服器副本、幾年後躺在證據櫃裡被傳票調走的副本,通通能開。
每條訊息一把臨時金鑰跑 Diffie–Hellman 這套(有時叫 sender forward secrecy / fire-and-forget encryption),把這個攻擊面整個鏟掉。代價是每次傳送多算幾毫秒密碼學。換來的是:未來的任何一個版本的你、任何一次入侵、任何一次配合法庭命令交出金鑰的情形,都沒辦法從離開你裝置之後的那些密文裡把明文撈回來。
你的過去,對你自己也是封閉的。這就是我們想要的屬性。
BlindPost