提(ti)升 Web 端 JavaScript 的可信度:WAICT 體系詳解
提升 Web 端 JavaScript 的可信度:WAICT 體系詳解

在(zai)當(dang)前互聯網時代(dai),網頁是(shi)最強大的(de)(de)(de)應用平臺。只要在(zai)瀏(liu)覽(lan)器(qi)中擁有(you)合適(shi)的(de)(de)(de) API,你理(li)論(lun)上(shang)可以安全(quan)運(yun)行任何你想運(yun)行的(de)(de)(de)東(dong)西。不過——除了(le)“加(jia)密(mi)學”這塊(kuai)。事實上(shang),自(zi) 2011 年以來,“網頁中的(de)(de)(de) JavaScript 加(jia)密(mi)”一說(shuo)就被(bei)認為是(shi)“不靠譜”的(de)(de)(de)。 其核心問題(ti)在(zai)于:代(dai)碼的(de)(de)(de)分發(fa)。如果(guo)我們在(zai)客戶端瀏(liu)覽(lan)器(qi)中生(sheng)成密(mi)鑰,從(cong)而讓用戶能夠發(fa)送/接收(shou)端對端加(jia)密(mi)消息(xi),那么(me)如果(guo)應用被(bei)篡改,惡意者究竟(jing)有(you)什么(me)阻止他們修改 JavaScript 代(dai)碼并將消息(xi)外泄呢?
相比(bi)之下,智能手機應(ying)用(yong)商店在這方面做得(de)比(bi)較完善:它(ta)們為應(ying)用(yong)生態提供(gong)了完整性保障(zhang)(確保所(suo)交付的(de)(de)應(ying)用(yong)未(wei)被篡(cuan)改)、一致性保障(zhang)(確保所(suo)有用(yong)戶獲取的(de)(de)是同一個版本(ben))以(yi)及透明(ming)性保障(zhang)(可見的(de)(de)版本(ben)記錄)。
如果(guo)我們能讓網(wang)頁(ye)也(ye)具備類(lei)似(si)屬性(xing)——也(ye)就是(shi)無需集中(zhong)式應(ying)用(yong)商店,也(ye)能為網(wang)頁(ye)應(ying)用(yong)提供“完整性(xing)”、“一致性(xing)”、“透明性(xing)”保障,那么對于網(wang)頁(ye)中(zhong)運行的加密、錢包、投票系統(tong)、機密 LLM 等都會大有裨益。
本文將介紹一(yi)個(ge)名為 Web Application Integrity, Consistency, and Transparency(WAICT)的(de)方案(Cloudflare 參(can)與(yu)了(le)其起草),這是一(yi)個(ge)由(you)瀏(liu)覽(lan)器廠商(shang)、云(yun)服務商(shang)、加(jia)密(mi)通信/應用開發者(zhe)聯合推動(dong)、在(zai) W3C 擁有支持背景的(de)項目。我們將先從問題定義談起,再(zai)逐(zhu)步構(gou)建解決方案。
一、定義“網頁應用”
在(zai)談安全保障之前,首先必須明(ming)確“網頁應用(yong)(web application)”是什么。智能手機上的應用(yong)可(ke)以看作(zuo)一個壓縮包(zip);網頁則由相互關聯的資源(yuan)組成——HTML、JavaScript、WASM、CSS 等,這些(xie)資源(yuan)既可(ke)能來自(zi)本域,也可(ke)能來自(zi)外域;而任一資源(yuan)變化,都可(ke)能大(da)幅改變應用(yong)行(xing)為(wei)。
因此,一個連貫的“應用”定義就要求:應用必須對其所加載的資源做出承諾(commit)。也(ye)就是說,需要(yao)有(you)機(ji)制讓瀏覽器知(zhi)道“這是這個應用應該加載的資(zi)源集合”。下面我們先從“完整(zheng)性(Integrity)”談起(qi)。
二、完整性:從 SRI 到 “完整性清單”
2.1 子資源完整性(Subresource Integrity, SRI)
網頁的一個重要機制是 SRI:瀏覽器允許頁面在 <script>、<link> 等標簽(qian)中指定外部(bu)資源(yuan)的哈希。示例如下(xia):
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.7/underscore-min.js"
integrity="sha512-dvWGkLATSdw5qWb2qozZBRKJ80Omy2YN/aF3wTUVC5+D1eqbA+TjWpPpoj8vorK5xGLMa2ZqIeWCpDZP/+pQGQ==">
</script>
瀏覽器會下載 underscore.js,然后校驗其 SHA-512 哈希是否與 integrity 屬性中的值匹配(pei)(pei);匹配(pei)(pei)則加載,否則拋錯、不執(zhi)行。
如果頁面中所有外部腳本、樣式等資源都帶有 SRI 屬性,那么整個頁面就可被其 HTML 定義。這距離我們想要的狀態已經很接近了。但網頁應用通常包含多個頁面,并且頁面之間還可能相互鏈接。換句話說:頁面無法強制其鏈接的“下一個頁面”的哈希。
2.2 完整性清單(Integrity Manifest)
為了讓整(zheng)個(ge)站(zhan)點(域)下的每個(ge)資源都受到完(wan)整(zheng)性保障,WAICT 提(ti)出了“完(wan)整(zheng)性清單(dan)”的機制:站(zhan)點向客戶端提(ti)供一(yi)個(ge) JSON 配(pei)置(zhi)文件(jian)(manifest),其內(nei)容包括(kuo):
- 一個“哈希字典(hashes)”,將資源的哈希值映射到其路徑。路徑為空字符串表示“任意路徑下可能的資源”(例如錯誤頁)。示例如下:
"hashes": {
"81db308d0df59b74d4a9bd25c546f25ec0fdb15a8d6d530c07a89344ae8eeb02": "/assets/js/main.js",
"fbd1d07879e672fd4557a2fa1bb2e435d88eac072f8903020a18672d5eddfb7c": "/index.html",
"5e737a67c38189a01f73040b06b4a0393b7ea71c86cf73744914bbb0cf0062eb": "/vendored/main.css",
"684ad58287ff2d085927cb1544c7d685ace897b6b25d33e46d2ec46a355b1f0e": "",
"f802517f1b2406e308599ca6f4c02d2ae28bb53ff2a5dbcddb538391cb6ad56a": ""
}
- 一個“完整性策略(integrity-policy)”,指定哪些類型的數據被強制檢查、如何檢查。例如:
"integrity-policy": "blocked-destinations=(script), checked-destinations=(wasm)"
將二者合起(qi)來后(hou),完整的(de) manifest 結構(gou)類似:
"manifest": {
"version": 1,
"integrity-policy": ...,
"hashes": ...
}
有了 SRI + 完整性清單,那么(me)整個站(zhan)點及其瀏(liu)覽(lan)器(qi)端所(suo)加載的資(zi)源(yuan)集合就由這個清單的哈希(xi)唯一決(jue)定。也就是說(shuo),整個網(wang)站(zhan)的狀態可被一個哈希(xi)值所(suo)承諾。
三、一致性與透明性:公開、可監控的日志機制
3.1 透明性的意義
“透明(ming)性(Transparency)”指的(de)是:應(ying)用的(de)代碼(ma)/資源被記錄(lu)在(zai)一個公開可(ke)訪問、只(zhi)增不刪(shan)的(de)日志中(zhong)。這樣做(zuo)有兩(liang)方面好(hao)處:
- 如果用戶被服務到惡意的代碼,且其察覺到了,他們可以向外部證明自己運行的是什么。
- 即便用戶沒有察覺,外部審計者也可能在歷史日志中發現惡意代碼。
注意:透明性不能防止惡意代碼的分發,但至少使其(qi)可(ke)審計。現(xian)在(zai),由于(yu)我(wo)們已把(ba)整個(ge)站點狀態濃縮為一個(ge)哈(ha)希,我(wo)們就可(ke)以讓這個(ge)哈(ha)希進(jin)入一個(ge)公開(kai)日志。以下(xia)是我(wo)們設(she)計時應滿(man)足(zu)的重(zhong)要要求:
- 不破壞已有站點 — 應可選擇性啟用,不影響現有網站功能。
- 不增加額外往返(round-trip)網絡請求。
- 尊重用戶隱私:不得要求用戶向新第三方識別/認證。
- 用戶無需保存站點特定數據(無狀態客戶端)。
- 無中心化:不能有單點失敗、單點信任。
- 啟用門檻低:站點運營方可以輕松加入日志。
- 停用也容易:站點可以退出日志機制。
- 停用透明化也要可被察覺:攻擊者不能悄悄退出機制。
- 監控功能:站點運營方應能監控其透明化狀態。
3.2 哈希鏈(Hash Chain)
日志(zhi)通(tong)常實現為追加(jia)(append-only)結構(gou),支持“包含證明(ming)(ming)(inclusion proof)”與(yu)“一(yi)致性證明(ming)(ming)(consistency proof)”。最(zui)簡單(dan)的(de)追加(jia)結構(gou)即哈希(xi)鏈:每個新元素的(de)哈希(xi)被串聯進鏈中,最(zui)終鏈哈希(xi)代表整條鏈。

通(tong)過哈希鏈即可構建包(bao)含證明(ming)和一致性證明(ming)。
3.3 為網站構建透明機制
每站日志(Per-Site Log)
首先(xian),為每個參與透明化(hua)的(de)站(zhan)點(dian)(dian)單獨(du)建(jian)立(li)一個日(ri)志(zhi)(哈希鏈)。該(gai)日(ri)志(zhi)中的(de)條目即該(gai)站(zhan)點(dian)(dian)在某(mou)時刻(ke)的(de)完整性清(qing)單(manifest)哈希。

但僅有(you)日(ri)志還不夠(gou),因(yin)為日(ri)志運營方(fang)若為惡意方(fang),仍(reng)可隨意“新(xin)增/刪(shan)除”條(tiao)目(mu)并重(zhong)新(xin)計算哈(ha)希(xi)鏈(lian)。為防止這種情(qing)況,我們引入(ru)“見(jian)證(zheng)(zheng)(zheng)者(zhe)(witness)”角色:見(jian)證(zheng)(zheng)(zheng)者(zhe)驗(yan)證(zheng)(zheng)(zheng)日(ri)志一致(zhi)性證(zheng)(zheng)(zheng)明,并對新(xin)的鏈(lian)哈(ha)希(xi)進行簽(qian)名。
客戶(hu)端(瀏覽器)在用(yong)戶(hu)訪(fang)問(wen)站點時,會收到:
- 該站點當前的 manifest ;
- 該 manifest 在站點日志中的包含證明;
- 見證者對日志鏈哈希的簽名。 瀏覽器驗證簽名、驗證包含證明、再執行完整性檢查。此時用戶可較為確知:該 manifest 已被記錄在日志中,且日志沒有被篡改/刪除。
透明服務(Transparency Service)
為了(le)維護所有(you)參與透明(ming)化的站點(dian)記錄,我們使用一個(ge)前綴樹(trie)結構,將「域(yu)名(ming) → 站點(dian)日志鏈(lian)哈(ha)希 + 鏈(lian)大小 + 資源托(tuo)管地址」做(zuo)映射。

站(zhan)點加入/更(geng)新/退出透(tou)明(ming)體系(xi)時,都會在該前綴樹(shu)中更(geng)新其條目。見證(zheng)(zheng)者需驗證(zheng)(zheng)該前綴樹(shu)更(geng)新證(zheng)(zheng)明(ming),并對根哈(ha)希進行(xing)簽(qian)名。
當用戶訪問站(zhan)(zhan)點(dian)(dian)時,瀏覽器除了(le)驗(yan)證(zheng)站(zhan)(zhan)點(dian)(dian)日志、還要驗(yan)證(zheng):站(zhan)(zhan)點(dian)(dian)日志是否(fou)在(zai)前綴(zhui)樹中包含、前綴(zhui)樹根簽名是否(fou)可信。
此外,為滿足“無額外往返請求”這一(yi)要求,瀏覽(lan)器可預(yu)裝一(yi)個「透(tou)明(ming)預(yu)加(jia)載列表(transparency preload list)」,其(qi)中列出(chu)已(yi)參與透(tou)明(ming)體系的站(zhan)點域名。若站(zhan)點出(chu)現在此列表中,則必須提供包含證明(ming)或非包含證明(ming)(證明(ming)其(qi)已(yi)退出(chu))。
監控、可退出、無單點
- 監控:前綴樹葉節點新增了 “created” 時間戳;站點運營方僅需監控“創建時間”和“日志條目數”即可判斷是否被篡改。
- 退出透明體系:站點提出退出時,葉節點不是直接刪除,而是置為“墓碑(tombstone)”形式,保留創建時間。
- 無單點:體系設計支持多個透明服務/見證者,“非中心化”以減少信任或失敗依賴。

四、一致性挑戰:樹不一致與時間不一致
4.1 樹不一致(Tree Inconsistency)
如(ru)果(guo)多個(ge)透明服(fu)務(wu)的前綴樹對某(mou)個(ge)站點記錄不(bu)一致(zhi)(zhi)(即鏈哈希不(bu)同),就(jiu)構成“樹不(bu)一致(zhi)(zhi)”。一種極端解決(jue)辦(ban)法(fa)是(shi)讓客戶端要求多個(ge)服(fu)務(wu)的包含證明,但這樣增(zeng)大負擔(dan)。
方案是(shi)限制透(tou)明服務(wu)的(de)數量(類似于(yu) Google Chrome 中采用的(de)證書透(tou)明度日志數量約(yue)為8條)。
4.2 時間不一致(Temporal Inconsistency)
時間不一(yi)致指:用(yong)戶(hu)可能因為地域(yu)、cookie 等(deng)因素(su),訪(fang)問到較(jiao)新(xin)的或較(jiao)舊(jiu)版(ban)本的站點。理論上,如果簽名有效期過(guo)長(chang)(如十(shi)年),站點可能一(yi)直提供非常舊(jiu)的版(ban)本而用(yong)戶(hu)不察。
雖然(ran)最強一致性(xing)(所有(you)用戶同時看到完(wan)全相(xiang)同版(ban)本(ben)(ben))難以(yi)實現(xian),但我們可以(yi)降低版(ban)本(ben)(ben)分叉(cha)的(de)規模。比如令(ling)見證者簽(qian)名(ming)根哈希的(de)有(you)效(xiao)期(qi)較短(例如一周),以(yi)限制可服務的(de)版(ban)本(ben)(ben)數(shu)量。缺點是:站(zhan)點即便未更新(xin),也需周期(qi)性(xing)向透明服務請(qing)求新(xin)的(de)簽(qian)名(ming)。
五、超越「完整性/一致性/透明性」:其他增強特性
5.1 代碼簽名(Code Signing)
WAICT 本(ben)(ben)身并不解決“代(dai)碼來自(zi)何處(chu)”的問題(ti)(即來源可追溯性)。例如,Alice 自(zi)己(ji)托管一個開源軟件版本(ben)(ben),Bob 如何確(que)定其與官方倉(cang)庫一致?
為此,與 WEBCAT(由 Freedom of the Press Foundation)協議整合:允許站點在 manifest 中加入擴展字段 dev-ids,列(lie)出已簽名站點資產的開發者身份(例如通(tong)過 Sigstore)。瀏覽器插(cha)件可讀取該(gai)字(zi)段(duan),從而建立信(xin)任。
5.2 冷卻期(Cooldown)機制
攻擊者若(ruo)想悄然(ran)(ran)退(tui)出(chu)透明(ming)體系或(huo)(huo)更換簽名(ming)開發者身(shen)份,可(ke)(ke)借助短期(qi)(qi)停(ting)頓。在預加(jia)載列表中注冊的站(zhan)點,客戶端可(ke)(ke)要(yao)求:“若(ruo)站(zhan)點出(chu)現該名(ming)單中,則必須(xu)為(wei)透明(ming)啟用狀態,或(huo)(huo)其退(tui)出(chu)狀態須(xu)已達冷卻期(qi)(qi)(如 24 小時)之后才接受”。這(zhe)樣攻擊者若(ruo)突然(ran)(ran)切換狀態,將被檢(jian)測。
六、部署考量
各角(jiao)色的(de)信任與(yu)資源需求如下(xia):
- 透明服務(Transparency Service):存儲所有透明化站點的元數據。若有 1 億域名、每條256 B數據,則單棵前綴樹約 26 GB(不含中間哈希)。運營方需具備高可用性且多個服務應無關聯宕機。
- 見證者(Witness):驗證前綴樹更新、簽名根哈希。存儲需求類似,需要高可用性并長期保管簽名私鑰。
- 資源托管方(Asset Host):存儲實際代碼/資源。信任要求低,因為瀏覽器已通過哈希校驗。但托管方不能篡改內容,僅可能拒絕服務。
- 客戶端(Client,即瀏覽器):執行所有檢查(包含證明、簽名、完整性等),是最需要信任的部分。
Cloudflare 表示愿(yuan)意(yi)在(zai)該(gai)生(sheng)態中提供透(tou)明服務及見證者角色(se),但(dan)會避免(mian)“自我見證”以防利益沖突。
支持替代生態系統
對于如 Tor Browser 這樣(yang)的匿名環(huan)境,可(ke)能不能信任現有透(tou)明服務。WAICT 支持將前綴樹(shu)托管到區塊鏈上,以滿足(zu)無(wu)中心(xin)化、無(wu)需傳統域名驗(yan)證(zheng)的環(huan)境需求。
七、下一步與總結
目前 WAICT 仍處(chu)于標準化的早期階段(duan)。下一步重點包括(kuo):
- 擴展 SRI 支持更多數據類型(例如 WASM、圖片)
- 標準化完整性清單格式
- 標準化附加特性(如代碼簽名、冷卻機制)
我們鼓勵開發者關注透明規(gui)范草(cao)案、參與討(tao)論、提交 PR 或 Issue(規(gui)范開源(yuan)于 GitHub)
八、小結:為什么這對你我很重要?
作為前端/全棧/安全工程師,我們往往假設“在瀏覽器中運行的 JavaScript 就是安全的”。但現實中很多安全問題源于 代碼分發的不確定性:代碼可能被替(ti)換、被篡改、版(ban)本可能混(hun)亂。WAICT 所提供(gong)的機(ji)制——完整(zheng)性清單 + 透(tou)明(ming)日志 + 前綴樹索引 +簽名機(ji)制——力圖為網頁應(ying)用構建一個類似于(yu)「應(ying)用商(shang)店簽名校驗」的信(xin)任層。
如果你在(zai)開發(fa)例(li)如網頁錢包、端(duan)(duan)對端(duan)(duan)加密應(ying)用(yong)(yong)、投(tou)票系統、在(zai)瀏覽器(qi)運行的 LLM 等敏感應(ying)用(yong)(yong),理解并盡(jin)早采用(yong)(yong)這些機制(zhi),將對你提(ti)升(sheng)安全(quan)性(xing)、合規性(xing)、用(yong)(yong)戶(hu)信任度都有重大(da)意義。
本文是由(you)葡萄城技術開發(fa)(fa)團隊發(fa)(fa)布,轉(zhuan)載請(qing)注明出處: