WhatsApp 白皮書(shū)(翻譯)

端對(duì)端加密(E2EE)-參考文章

簡(jiǎn)介

本白皮書(shū)提供了 WhatsApp 端到端加密系統(tǒng)的技術(shù)說(shuō)明枢步。請(qǐng)?jiān)L問(wèn) WhatsApp 的網(wǎng)站 www.whatsapp.com/security 了解更多。
WhatsApp Messenger 允許人們自由的交換消息(包括聊天,群聊植影,圖片喘沿,視頻暑劝,語(yǔ)音消息和文件)铜邮,并在發(fā)送者和接收者之間使用端對(duì)端加密(在 2016 年 3 月 31 之后的版本)舅桩。
Signal 協(xié)議是由 Open Whisper Systems (非盈利軟件開(kāi)發(fā)團(tuán)體)設(shè)計(jì)酱虎,是 WhatsApp 端對(duì)端加密的基礎(chǔ)。這種端對(duì)端加密協(xié)議旨在防止第三方和 WhatsApp 對(duì)消息或通話進(jìn)行明文訪問(wèn)擂涛。更重要的是读串,即使用戶(hù)設(shè)備的密鑰泄露,也不能解密之前傳輸?shù)南ⅰ?br> 本文檔概述了 Singal 協(xié)議在 WhatsApp 中的應(yīng)用撒妈。

術(shù)語(yǔ)

公鑰類(lèi)型

  • 身份密鑰對(duì)(Identity Key Pair) —— 一個(gè)長(zhǎng)期 Curve25519 密鑰對(duì)恢暖,安裝時(shí)生成。
  • 已簽名的預(yù)共享密鑰(Signed Pre Key) —— 一個(gè)中期 Curve25519 密鑰對(duì)狰右,安裝時(shí)生成杰捂,由身份密鑰簽名,并定期進(jìn)行輪換棋蚌。
  • 一次性預(yù)共享密鑰(One-Time Pre Keys) —— 一次性使用的 Curve25519 密鑰對(duì)隊(duì)列嫁佳,安裝時(shí)生成,不足時(shí)補(bǔ)充附鸽。

會(huì)話密鑰類(lèi)型

  • 根密鑰(Root Key) —— 32 字節(jié)的值脱拼,用于創(chuàng)建鏈密鑰。
  • 鏈密鑰(Chain Key) —— 32 字節(jié)的值坷备,用于創(chuàng)建消息密鑰。
  • 消息密鑰(Message Key) —— 80 個(gè)字節(jié)的值情臭,用于加密消息內(nèi)容省撑。32 個(gè)字節(jié)用于 AES-256 密鑰,32 個(gè)字節(jié)用于 HMAC-SHA256 密鑰俯在,16 個(gè)字節(jié)用于 IV竟秫。

客戶(hù)端注冊(cè)

在注冊(cè)時(shí),WhatsApp 客戶(hù)端將身份公鑰(public Identity Key)跷乐、已簽名的預(yù)共享公鑰(public Signed Pre Key)和一批一次性預(yù)共享公鑰(One-Time Pre Keys)發(fā)送給服務(wù)器肥败。WhatsApp 服務(wù)器存儲(chǔ)用戶(hù)身份相關(guān)的公鑰。WhatsApp 服務(wù)器無(wú)法訪問(wèn)任何客戶(hù)端的私鑰愕提。

會(huì)話初始化設(shè)置

要與另一個(gè) WhatsApp 用戶(hù)通信馒稍,WhatsApp 客戶(hù)端需要先建立一個(gè)加密會(huì)話。加密會(huì)話一旦被創(chuàng)建浅侨,客戶(hù)端就不需要再重復(fù)創(chuàng)建會(huì)話纽谒,除非會(huì)話失效(例如重新安裝應(yīng)用或更換設(shè)備)。

建立會(huì)話:

  1. 會(huì)話發(fā)起人為接收人申請(qǐng)身份公鑰(public Identity Key)如输、已簽名的預(yù)共享公鑰(public Signed Pre Key)和一個(gè)一次性預(yù)共享密鑰(One-Time Pre Key)鼓黔。
  2. 服務(wù)器返回所請(qǐng)求的公鑰央勒。一次性預(yù)共享密鑰(One-Time Pre Key)僅使用一次,因此請(qǐng)求完成后將從服務(wù)器刪除澳化。如果一次性預(yù)共享密鑰(One-Time Pre Key)被用完且尚未補(bǔ)充崔步,則返回空。
  3. 發(fā)起人將接收人的身份密鑰(Identity Key)存為 Irecipient缎谷,將已簽名的預(yù)共享密鑰(Signed Pre Key)存為 Srecipient井濒,將一次性預(yù)共享密鑰(One-Time Pre Key)存為 Orecipient。
  4. 發(fā)起者生成一個(gè)臨時(shí)的 Curve25519 密鑰對(duì) —— Einitiator
  5. 發(fā)起者加載自己的身份密鑰(Identity Key)作為 Iinitiator
  6. 發(fā)起者計(jì)算主密鑰 master_secret = ECDH ( Iinitiator, Srecipient ) || ECDH ( Einitiator, Irecipient ) || ECDH ( Einitiator, Srecipient ) || ECDH ( Einitiator, Orecipient ) 慎陵。如果沒(méi)有一次性預(yù)共享密鑰(One-Time Pre Key)眼虱,最終 ECDH 將被忽略。
  7. 發(fā)起者使用 HKDF 算法從 master_secret 創(chuàng)建一個(gè)根密鑰(Root Key)和鏈密鑰(Chain Keys)席纽。

接收會(huì)話設(shè)置
在建立長(zhǎng)期加密會(huì)話后捏悬,發(fā)起人可以立即向接收人發(fā)送消息,即使接收人處理離線狀態(tài)润梯。在接收方響應(yīng)之前过牙,發(fā)起方所有的消息都會(huì)包含創(chuàng)建會(huì)話所需的信息(在消息的 header 里)。其中包括發(fā)起人的 Einitiator 和 Iinitiator 纺铭。當(dāng)接收方收到包含會(huì)話設(shè)置的消息時(shí):

  1. 接收人使用自己的私鑰和消息 header 里的公鑰來(lái)計(jì)算相應(yīng)的主密鑰
  2. 接收人刪除發(fā)起人使用的一次性預(yù)共享密鑰(One-Time Pre Key)
  3. 發(fā)起人使用 HKDF 算法從主密鑰派生出相應(yīng)的根密鑰(Root Key)和鏈密鑰(Chain Keys)

交換消息
一旦建立了會(huì)話寇钉,通過(guò) AES256 消息密鑰加密(CbC 模式)和 HMAC-SHA256 驗(yàn)證來(lái)保護(hù)客戶(hù)端交換消息。
消息密鑰是短暫的且在每次發(fā)送消息后都會(huì)變化舶赔,使得用于加密消息的消息密鑰不能從已發(fā)送或已接收后的會(huì)話狀態(tài)中重建扫倡。
消息密鑰在發(fā)送消息時(shí)對(duì)發(fā)送人的鏈密鑰(Chain Key)進(jìn)行向前的“棘輪(ratchets)”派生而來(lái)。此外竟纳,每次消息巡回都執(zhí)行一個(gè)新的 ECDH 協(xié)議以創(chuàng)建一個(gè)新的鏈密鑰(Chain Key)撵溃。通過(guò)組合即時(shí) “哈希棘輪(hash ratchet)” 和巡回 “DH 棘輪(DH ratchet)” 提供前向安全。

通過(guò)鏈密鑰(Chain Key)計(jì)算消息密鑰(Message Key)
消息發(fā)送者每次需要新的消息密鑰時(shí)锥累,計(jì)算如下:

  1. 消息密鑰(Message Key)= HMAC-SHA256(Chain Key, 0x01)
  2. 鏈密鑰(Chain Key)隨后更新為: 鏈密鑰(Chain Key) = HMAC-SHA256(Chain Key, 0x02)

這樣形成向前“棘輪(ratchets)”鏈密鑰(Chain Key)缘挑,這也意味不能使用存儲(chǔ)的消息密鑰推導(dǎo)出當(dāng)前或過(guò)去的鏈密鑰(Chain Key)值。

通過(guò)根密鑰(Root Key)計(jì)算鏈密鑰(Chain Key)
每一條發(fā)送的消息都附帶一個(gè)短期的 Curve25519 公鑰桶略。一旦收到響應(yīng)语淘,新的鏈密鑰(Chain Key)計(jì)算如下:

  1. ephemeral_secret = ECDH(Ephemeralsender, Ephemeralrecipient)
  2. 鏈密鑰(Chain Key),根密鑰(Root Key)= HKDF(Root Key, ephemeral_secret)

一個(gè)鏈密鑰只能給一個(gè)用戶(hù)發(fā)消息际歼,所以消息密鑰不能被重用惶翻。由于消息密鑰和鏈密鑰(Chain Keys)的計(jì)算方式,消息可能會(huì)延遲蹬挺、亂序或完全丟失而不會(huì)有問(wèn)題维贺。

傳輸媒體和附件
任何類(lèi)型的大附件(視頻,音頻巴帮,圖像或文件)也都是端對(duì)端加密的:

  1. 發(fā)件人(發(fā)消息的 WhatsApp 用戶(hù))生成一個(gè) 32 字節(jié)的 AES256 臨時(shí)密鑰和一個(gè) 32 字節(jié)HMAC-SHA256 臨時(shí)密鑰溯泣。
  2. 發(fā)件人通過(guò) AES256 密鑰(CBC 模式)和隨機(jī) IV 給附件加密虐秋,然后附加使用 HMAC-SHA256 密文的 MAC。
  3. 發(fā)件人將加密的附件以上傳到服務(wù)器以二進(jìn)制存儲(chǔ)垃沦。
  4. 發(fā)件人給收件人發(fā)送一個(gè)包含加密密鑰客给、HMAC 密鑰、加密二進(jìn)制的 SHA256 哈希值和指向二進(jìn)制存儲(chǔ)的指針的加密消息
  5. 收件人解密消息肢簿,從服務(wù)器檢索加密的二進(jìn)制數(shù)據(jù)靶剑,驗(yàn)證 AES256 哈希,驗(yàn)證 MAC并解密為明文池充。

群組消息
傳統(tǒng)未加密的聊天應(yīng)用通常對(duì)群組消息使用“服務(wù)器扇出(server-side fan-out)”來(lái)發(fā)群組消息桩引。當(dāng)一個(gè)用戶(hù)向群組發(fā)消息時(shí),服務(wù)器將消息分發(fā)給每一個(gè)群組成員收夸。
而“客戶(hù)端扇出(client-side fan-out)”是客戶(hù)端將消息發(fā)給每一個(gè)群組成員坑匠。
WhatsApp 的群組消息基于上面列出的成對(duì)加密會(huì)話構(gòu)建,以便高效實(shí)現(xiàn)大量群組消息通過(guò)服務(wù)器扇出(server-side fan-out)卧惜。這是通過(guò) Signal 傳輸協(xié)議(Signal Messaging Protocol)的 “發(fā)送者密鑰(Sender Keys)”來(lái)完成的厘灼。
WhatsApp 群組成員第一次發(fā)消息到群組:

  1. 發(fā)送人生成一個(gè)隨機(jī) 32 字節(jié)的鏈密鑰(Chain Key)。
  2. 發(fā)送人生成一個(gè)隨機(jī) Curve25519 簽名密鑰對(duì)咽瓷。
  3. 發(fā)送人將 32 位鏈密鑰(Chain Key)和簽名密鑰中的公鑰組合成消息發(fā)送人密鑰(Sender Key)设凹。
  4. 發(fā)件人用成對(duì)傳輸協(xié)議為每個(gè)群組成員單獨(dú)加密發(fā)送人密鑰(Sender Keys)。

所有后續(xù)發(fā)給該群組的消息:

  1. 發(fā)送人從鏈密鑰(Chain Key)中獲取消息密鑰(Message Key)并更新鏈密鑰(Chain Key)
  2. 發(fā)送人在 CbC 模式下使用 AES256 加密消息
  3. 發(fā)送人使用簽名密鑰(Signature Key)簽名密文
  4. 發(fā)送人將單個(gè)密文消息發(fā)給服務(wù)器茅姜,服務(wù)器將消息分發(fā)給所有群組成員

消息發(fā)送人鏈密鑰(Chain Key)的“哈希棘輪(hash ratchet)”提供向前安全闪朱。當(dāng)群組成員離開(kāi)時(shí)時(shí),所有剩下的群組成員都清除發(fā)送人密鑰(Sender Key)并重新生成钻洒。

通話設(shè)置
WhatsApp 語(yǔ)音和視頻通話也是端對(duì)端加密监透。當(dāng) WhatsApp 用戶(hù)發(fā)起語(yǔ)音或視頻通話時(shí):

  1. 發(fā)起人與接收人建立加密會(huì)話(如果還沒(méi)有建立過(guò))
  2. 發(fā)起人生成一個(gè)隨機(jī) 32 字節(jié)的安全實(shí)時(shí)傳輸協(xié)議(SRTP) 主密鑰(master secret)
  3. 發(fā)起人向接收人發(fā)送一個(gè)包含安全實(shí)時(shí)傳輸協(xié)議(SRTP)主密鑰的加密消息用于發(fā)通話信號(hào)
  4. 如果應(yīng)答了呼叫,跟著發(fā)起安全實(shí)時(shí)傳輸協(xié)議(SRTP)呼叫

狀態(tài)
WhatsApp 狀態(tài)加密方式和群組消息非常相似航唆。給指定的一組接收人第一次發(fā)狀態(tài)遵循向群組第一次發(fā)消息相同的步驟。類(lèi)似地院刁,給同一組接收人發(fā)送后續(xù)狀態(tài)也遵循發(fā)群組消息相同的步驟糯钙。當(dāng)狀態(tài)發(fā)送人更改狀態(tài)隱私設(shè)置或從地址簿種刪除號(hào)碼來(lái)刪除接收人時(shí),狀態(tài)發(fā)送人會(huì)清除發(fā)送人密鑰(Sender Key)并重新生成退腥。

驗(yàn)證密鑰
WhatsApp 用戶(hù)還可以驗(yàn)證與之通信用戶(hù)的密鑰任岸,以便他們能夠確認(rèn)未授權(quán)的第三方(或 WhatsApp)未發(fā)起中間人攻擊。通過(guò)掃描二維碼或通過(guò)比較 60 位數(shù)字來(lái)完成狡刘。
二維碼包括:

  1. 版本號(hào)
  2. 雙方的用戶(hù)身份
  3. 雙方完整的 32 字節(jié)身份公鑰

當(dāng)用戶(hù)掃描對(duì)方的二維碼時(shí)享潜,將比較這些密鑰以確保二維碼中的身份密鑰與服務(wù)器檢索到的相匹配。
通過(guò)拼接兩個(gè)用戶(hù)身份密鑰的 30 位數(shù)字指紋來(lái)計(jì)算 60 位數(shù)字號(hào)碼嗅蔬。計(jì)算 30 位數(shù)字指紋步驟:

  1. 重復(fù) SHA-512 哈希身份公鑰和用戶(hù)標(biāo)識(shí)符 5200 次
  2. 獲取最后輸出哈希的前 30 個(gè)字節(jié)
  3. 將 30 個(gè)字節(jié)分成 6 組每組 5 字節(jié)的數(shù)據(jù)塊
  4. 通過(guò)解析每組 5 字節(jié)數(shù)據(jù)塊為 big-endian 無(wú)符號(hào)整形并且取模 10 萬(wàn)次轉(zhuǎn)換為 5 個(gè)數(shù)字
  5. 把六組每組 5 個(gè)數(shù)字連接成 30 位數(shù)字

傳輸安全
WhatsApp 客戶(hù)端和服務(wù)器之間所有通信都在單獨(dú)的加密通道內(nèi)分層剑按。在 Windows Phone疾就、iPhone 和 Android 上,這些端對(duì)端加密客戶(hù)端可以使用噪音管道(Noise Pipes)艺蝴,使用噪聲協(xié)議框架(Noise Protocol Framework)中的 Curve25519猬腰、AES-GCM 和 SHA256 實(shí)現(xiàn)長(zhǎng)期運(yùn)行的交互連接。
這為客戶(hù)端提供了一些不錯(cuò)的屬性:

  1. 極快的輕量級(jí)連接設(shè)置和恢復(fù)
  2. 加密隱藏元數(shù)據(jù)防止未授權(quán)的網(wǎng)絡(luò)監(jiān)聽(tīng)猜敢。沒(méi)有透露連接用戶(hù)身份相關(guān)的信息姑荷。
  3. 服務(wù)器上不存儲(chǔ)客戶(hù)端的安全認(rèn)證信息∷趵蓿客戶(hù)端使用 Curve25519 密鑰進(jìn)行身份驗(yàn)證鼠冕,因此服務(wù)器僅保存客戶(hù)端認(rèn)證公鑰(public authentication key)。如果服務(wù)器的用戶(hù)數(shù)據(jù)庫(kù)被入侵胯盯,也不會(huì)泄露個(gè)人認(rèn)證憑證懈费。

結(jié)論
WhatsApp 用戶(hù)之間的消息受到端對(duì)端加密協(xié)議的保護(hù),因此第三方和 WhatsApp 都無(wú)法獲知消息內(nèi)容陨闹,消息只能由接收人解密楞捂。所有 WhatsApp 消息(包括聊天、群聊趋厉、圖片寨闹、視頻、語(yǔ)音消息和文件)和 WhatsApp 通話都受到端對(duì)端加密的保護(hù)君账。
WhatsApp 服務(wù)器無(wú)法訪問(wèn) WhatsApp 用戶(hù)的私鑰繁堡,并且 WhatsApp 用戶(hù)可以選擇驗(yàn)證密鑰以確保其通訊完整。
WhatsApp 使用的 Signal 協(xié)議庫(kù)是開(kāi)源的乡数,代碼:https://github.com/whispersystems/libsignal-protocol-java/

參考
維基百科:端到端加密
Signal 協(xié)議中的雙棘輪算法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市净赴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翼馆,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件金度,死亡現(xiàn)場(chǎng)離奇詭異应媚,居然都是意外死亡猜极,警方通過(guò)查閱死者的電腦和手機(jī)中姜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)跟伏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)丢胚,“玉大人翩瓜,你說(shuō)我怎么就攤上這事∈茸溃” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵浮定,是天一觀的道長(zhǎng)层亿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)匿又,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任裕偿,我火速辦了婚禮痛单,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘旭绒。我一直安慰自己,他們只是感情好重父,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布忽匈。 她就那樣靜靜地躺著,像睡著了一般丹允。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天萎羔,我揣著相機(jī)與錄音碳默,去河邊找鬼缘眶。 笑死,一個(gè)胖子當(dāng)著我的面吹牛巷懈,可吹牛的內(nèi)容都是我干的慌洪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼涌攻,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼频伤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起憋肖,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤岸更,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后坐慰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赞咙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年糟港,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片速和。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡剥汤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吭敢,到底是詐尸還是另有隱情,我是刑警寧澤欲低,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站瑞筐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏聚假。R本人自食惡果不足惜扫步,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闯袒。 院中可真熱鬧游岳,春花似錦、人聲如沸胚迫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)期犬。三九已至河哑,卻和暖如春龟虎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背佳吞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工棉安, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贡耽。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像算芯,于是被迫代替她去往敵國(guó)和親凳宙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355