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

在當前互聯(lián)網(wǎng)時代,網(wǎng)頁是最強大的應(yīng)用平臺。只要在瀏覽器中擁有合適的 API,你理論上可以安全運行任何你想運行的東西。不過——除了“加密學(xué)”這塊。事實上,自 2011 年以來,“網(wǎng)頁中的 JavaScript 加密”一說就被認為是“不靠譜”的。 其核心問題在于:代碼的分發(fā)。如果我們在客戶端瀏覽器中生成密鑰,從而讓用戶能夠發(fā)送/接收端對端加密消息,那么如果應(yīng)用被篡改,惡意者究竟有什么阻止他們修改 JavaScript 代碼并將消息外泄呢?
相比之下,智能手機應(yīng)用商店在這方面做得比較完善:它們?yōu)閼?yīng)用生態(tài)提供了完整性保障(確保所交付的應(yīng)用未被篡改)、一致性保障(確保所有用戶獲取的是同一個版本)以及透明性保障(可見的版本記錄)。
如果我們能讓網(wǎng)頁也具備類似屬性——也就是無需集中式應(yīng)用商店,也能為網(wǎng)頁應(yīng)用提供“完整性”、“一致性”、“透明性”保障,那么對于網(wǎng)頁中運行的加密、錢包、投票系統(tǒng)、機密 LLM 等都會大有裨益。
本文將介紹一個名為 Web Application Integrity, Consistency, and Transparency(WAICT)的方案(Cloudflare 參與了其起草),這是一個由瀏覽器廠商、云服務(wù)商、加密通信/應(yīng)用開發(fā)者聯(lián)合推動、在 W3C 擁有支持背景的項目。我們將先從問題定義談起,再逐步構(gòu)建解決方案。
一、定義“網(wǎng)頁應(yīng)用”
在談安全保障之前,首先必須明確“網(wǎng)頁應(yīng)用(web application)”是什么。智能手機上的應(yīng)用可以看作一個壓縮包(zip);網(wǎng)頁則由相互關(guān)聯(lián)的資源組成——HTML、JavaScript、WASM、CSS 等,這些資源既可能來自本域,也可能來自外域;而任一資源變化,都可能大幅改變應(yīng)用行為。
因此,一個連貫的“應(yīng)用”定義就要求:應(yīng)用必須對其所加載的資源做出承諾(commit)。也就是說,需要有機制讓瀏覽器知道“這是這個應(yīng)用應(yīng)該加載的資源集合”。下面我們先從“完整性(Integrity)”談起。
二、完整性:從 SRI 到 “完整性清單”
2.1 子資源完整性(Subresource Integrity, SRI)
網(wǎng)頁的一個重要機制是 SRI:瀏覽器允許頁面在 <script>、<link> 等標簽中指定外部資源的哈希。示例如下:
<script src="https://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 屬性中的值匹配;匹配則加載,否則拋錯、不執(zhí)行。
如果頁面中所有外部腳本、樣式等資源都帶有 SRI 屬性,那么整個頁面就可被其 HTML 定義。這距離我們想要的狀態(tài)已經(jīng)很接近了。但網(wǎng)頁應(yīng)用通常包含多個頁面,并且頁面之間還可能相互鏈接。換句話說:頁面無法強制其鏈接的“下一個頁面”的哈希。
2.2 完整性清單(Integrity Manifest)
為了讓整個站點(域)下的每個資源都受到完整性保障,WAICT 提出了“完整性清單”的機制:站點向客戶端提供一個 JSON 配置文件(manifest),其內(nèi)容包括:
- 一個“哈希字典(hashes)”,將資源的哈希值映射到其路徑。路徑為空字符串表示“任意路徑下可能的資源”(例如錯誤頁)。示例如下:
"hashes": {
"81db308d0df59b74d4a9bd25c546f25ec0fdb15a8d6d530c07a89344ae8eeb02": "/assets/js/main.js",
"fbd1d07879e672fd4557a2fa1bb2e435d88eac072f8903020a18672d5eddfb7c": "/index.html",
"5e737a67c38189a01f73040b06b4a0393b7ea71c86cf73744914bbb0cf0062eb": "/vendored/main.css",
"684ad58287ff2d085927cb1544c7d685ace897b6b25d33e46d2ec46a355b1f0e": "",
"f802517f1b2406e308599ca6f4c02d2ae28bb53ff2a5dbcddb538391cb6ad56a": ""
}
- 一個“完整性策略(integrity-policy)”,指定哪些類型的數(shù)據(jù)被強制檢查、如何檢查。例如:
"integrity-policy": "blocked-destinations=(script), checked-destinations=(wasm)"
將二者合起來后,完整的 manifest 結(jié)構(gòu)類似:
"manifest": {
"version": 1,
"integrity-policy": ...,
"hashes": ...
}
有了 SRI + 完整性清單,那么整個站點及其瀏覽器端所加載的資源集合就由這個清單的哈希唯一決定。也就是說,整個網(wǎng)站的狀態(tài)可被一個哈希值所承諾。
三、一致性與透明性:公開、可監(jiān)控的日志機制
3.1 透明性的意義
“透明性(Transparency)”指的是:應(yīng)用的代碼/資源被記錄在一個公開可訪問、只增不刪的日志中。這樣做有兩方面好處:
- 如果用戶被服務(wù)到惡意的代碼,且其察覺到了,他們可以向外部證明自己運行的是什么。
- 即便用戶沒有察覺,外部審計者也可能在歷史日志中發(fā)現(xiàn)惡意代碼。
注意:透明性不能防止惡意代碼的分發(fā),但至少使其可審計。現(xiàn)在,由于我們已把整個站點狀態(tài)濃縮為一個哈希,我們就可以讓這個哈希進入一個公開日志。以下是我們設(shè)計時應(yīng)滿足的重要要求:
- 不破壞已有站點 — 應(yīng)可選擇性啟用,不影響現(xiàn)有網(wǎng)站功能。
- 不增加額外往返(round-trip)網(wǎng)絡(luò)請求。
- 尊重用戶隱私:不得要求用戶向新第三方識別/認證。
- 用戶無需保存站點特定數(shù)據(jù)(無狀態(tài)客戶端)。
- 無中心化:不能有單點失敗、單點信任。
- 啟用門檻低:站點運營方可以輕松加入日志。
- 停用也容易:站點可以退出日志機制。
- 停用透明化也要可被察覺:攻擊者不能悄悄退出機制。
- 監(jiān)控功能:站點運營方應(yīng)能監(jiān)控其透明化狀態(tài)。
3.2 哈希鏈(Hash Chain)
日志通常實現(xiàn)為追加(append-only)結(jié)構(gòu),支持“包含證明(inclusion proof)”與“一致性證明(consistency proof)”。最簡單的追加結(jié)構(gòu)即哈希鏈:每個新元素的哈希被串聯(lián)進鏈中,最終鏈哈希代表整條鏈。

通過哈希鏈即可構(gòu)建包含證明和一致性證明。
3.3 為網(wǎng)站構(gòu)建透明機制
每站日志(Per-Site Log)
首先,為每個參與透明化的站點單獨建立一個日志(哈希鏈)。該日志中的條目即該站點在某時刻的完整性清單(manifest)哈希。

但僅有日志還不夠,因為日志運營方若為惡意方,仍可隨意“新增/刪除”條目并重新計算哈希鏈。為防止這種情況,我們引入“見證者(witness)”角色:見證者驗證日志一致性證明,并對新的鏈哈希進行簽名。
客戶端(瀏覽器)在用戶訪問站點時,會收到:
- 該站點當前的 manifest ;
- 該 manifest 在站點日志中的包含證明;
- 見證者對日志鏈哈希的簽名。 瀏覽器驗證簽名、驗證包含證明、再執(zhí)行完整性檢查。此時用戶可較為確知:該 manifest 已被記錄在日志中,且日志沒有被篡改/刪除。
透明服務(wù)(Transparency Service)
為了維護所有參與透明化的站點記錄,我們使用一個前綴樹(trie)結(jié)構(gòu),將「域名 → 站點日志鏈哈希 + 鏈大小 + 資源托管地址」做映射。

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

四、一致性挑戰(zhàn):樹不一致與時間不一致
4.1 樹不一致(Tree Inconsistency)
如果多個透明服務(wù)的前綴樹對某個站點記錄不一致(即鏈哈希不同),就構(gòu)成“樹不一致”。一種極端解決辦法是讓客戶端要求多個服務(wù)的包含證明,但這樣增大負擔。
方案是限制透明服務(wù)的數(shù)量(類似于 Google Chrome 中采用的證書透明度日志數(shù)量約為8條)。
4.2 時間不一致(Temporal Inconsistency)
時間不一致指:用戶可能因為地域、cookie 等因素,訪問到較新的或較舊版本的站點。理論上,如果簽名有效期過長(如十年),站點可能一直提供非常舊的版本而用戶不察。
雖然最強一致性(所有用戶同時看到完全相同版本)難以實現(xiàn),但我們可以降低版本分叉的規(guī)模。比如令見證者簽名根哈希的有效期較短(例如一周),以限制可服務(wù)的版本數(shù)量。缺點是:站點即便未更新,也需周期性向透明服務(wù)請求新的簽名。
五、超越「完整性/一致性/透明性」:其他增強特性
5.1 代碼簽名(Code Signing)
WAICT 本身并不解決“代碼來自何處”的問題(即來源可追溯性)。例如,Alice 自己托管一個開源軟件版本,Bob 如何確定其與官方倉庫一致?
為此,與 WEBCAT(由 Freedom of the Press Foundation)協(xié)議整合:允許站點在 manifest 中加入擴展字段 dev-ids,列出已簽名站點資產(chǎn)的開發(fā)者身份(例如通過 Sigstore)。瀏覽器插件可讀取該字段,從而建立信任。
5.2 冷卻期(Cooldown)機制
攻擊者若想悄然退出透明體系或更換簽名開發(fā)者身份,可借助短期停頓。在預(yù)加載列表中注冊的站點,客戶端可要求:“若站點出現(xiàn)該名單中,則必須為透明啟用狀態(tài),或其退出狀態(tài)須已達冷卻期(如 24 小時)之后才接受”。這樣攻擊者若突然切換狀態(tài),將被檢測。
六、部署考量
各角色的信任與資源需求如下:
- 透明服務(wù)(Transparency Service):存儲所有透明化站點的元數(shù)據(jù)。若有 1 億域名、每條256 B數(shù)據(jù),則單棵前綴樹約 26 GB(不含中間哈希)。運營方需具備高可用性且多個服務(wù)應(yīng)無關(guān)聯(lián)宕機。
- 見證者(Witness):驗證前綴樹更新、簽名根哈希。存儲需求類似,需要高可用性并長期保管簽名私鑰。
- 資源托管方(Asset Host):存儲實際代碼/資源。信任要求低,因為瀏覽器已通過哈希校驗。但托管方不能篡改內(nèi)容,僅可能拒絕服務(wù)。
- 客戶端(Client,即瀏覽器):執(zhí)行所有檢查(包含證明、簽名、完整性等),是最需要信任的部分。
Cloudflare 表示愿意在該生態(tài)中提供透明服務(wù)及見證者角色,但會避免“自我見證”以防利益沖突。
支持替代生態(tài)系統(tǒng)
對于如 Tor Browser 這樣的匿名環(huán)境,可能不能信任現(xiàn)有透明服務(wù)。WAICT 支持將前綴樹托管到區(qū)塊鏈上,以滿足無中心化、無需傳統(tǒng)域名驗證的環(huán)境需求。
七、下一步與總結(jié)
目前 WAICT 仍處于標準化的早期階段。下一步重點包括:
- 擴展 SRI 支持更多數(shù)據(jù)類型(例如 WASM、圖片)
- 標準化完整性清單格式
- 標準化附加特性(如代碼簽名、冷卻機制)
我們鼓勵開發(fā)者關(guān)注透明規(guī)范草案、參與討論、提交 PR 或 Issue(規(guī)范開源于 GitHub)
八、小結(jié):為什么這對你我很重要?
作為前端/全棧/安全工程師,我們往往假設(shè)“在瀏覽器中運行的 JavaScript 就是安全的”。但現(xiàn)實中很多安全問題源于 代碼分發(fā)的不確定性:代碼可能被替換、被篡改、版本可能混亂。WAICT 所提供的機制——完整性清單 + 透明日志 + 前綴樹索引 +簽名機制——力圖為網(wǎng)頁應(yīng)用構(gòu)建一個類似于「應(yīng)用商店簽名校驗」的信任層。
如果你在開發(fā)例如網(wǎng)頁錢包、端對端加密應(yīng)用、投票系統(tǒng)、在瀏覽器運行的 LLM 等敏感應(yīng)用,理解并盡早采用這些機制,將對你提升安全性、合規(guī)性、用戶信任度都有重大意義。
浙公網(wǎng)安備 33010602011771號