Canvas 指紋雜訊若處理不當會適得其反。了解朴素隨機化為何可被偵測,以及 Brave 的 farbling 如何規避陷阱。
Canvas 雜訊——在瀏覽器傳回像素資料時注入細微隨機差異的做法——聽起來是個優雅的解決方案。每次改變雜湊值,追蹤器就無法給你的裝置釘上穩定的識別碼。但在實務中,情況遠比這複雜:設計粗糙的雜訊只需兩次 API 呼叫便能被偵測出來,而一旦被偵測到,你就會被歸類為隱私工具使用者。本文將解析雜訊的運作原理、隨機化為何會適得其反、結構化雜訊與朴素隨機性的本質區別,以及 Brave 的 farbling 機制如何規避了大多數陷阱——儘管它本身也留下了一些痕跡。
核心要點
- Canvas 雜訊的目標是透過隨機化追蹤指令碼讀取的像素來破壞穩定指紋。
- 朴素的隨機化只需兩次 API 呼叫便可被偵測:如果同一畫布每次傳回不同的像素,說明有東西在修改輸出。
- 結構化的、按工作階段和來源生成的雜訊(如 Brave 的 farbling)可以規避這一破綻,但仍然會暴露保護機制的存在。
- 趨同——讓你的 Canvas 輸出與大多數人保持一致——比隨機化能提供更強的匿名性。
- 雜訊大小至關重要:太大在統計上過於明顯;太小則可能被多次取樣平均消除。
Canvas 雜訊如何運作
Canvas 指紋指令碼繪製一個固定場景,然後透過 toDataURL() 或 getImageData() 讀回像素。這些像素編碼了你的 GPU、字型引擎和顯示卡驅動程式——這些硬體屬性在頁面載入之間保持不變。Canvas 雜訊工具攔截讀取操作,在資料到達指令碼之前對其進行修改。
主要有兩種修改方式:
攔截或置空。 傳回空畫布、全白結果或拋出錯誤。這能完全阻止指紋採集,但立刻就會暴露:空白結果本身就是一種指紋——每個使用此設定的訪客看起來一模一樣。一個簡單的 data.every(b => b === 0) 檢查就能發現它。
注入雜訊。 保留真實像素但稍加擾動——例如在隨機的 RGB 色版上加減 ±1 或 ±2——使雜湊值改變,同時視覺效果保持合理。大多數隱私擴充套件(CanvasBlocker、JShelter)和 Brave 的 farbling 都採用這種方式。
關鍵的設計問題在於:雜訊種子是如何生成的? 種子策略決定了雜訊是否可被偵測、是否可被還原。
為什麼朴素的隨機化可被偵測
假設某個雜訊工具在每次 API 呼叫時都生成全新的隨機種子。對同一塊未修改的畫布呼叫 getImageData() 兩次,得到的是兩個不同的位元組陣列。而這在真實瀏覽器中永遠不會發生——畫布是一個點陣圖,在兩次讀取之間沒有任何繪製操作的情況下,結果應該完全相同。一個對 API 呼叫兩次並比較輸出的指紋指令碼會立刻得出結論:雜訊存在。
這不是理論上的攻擊。Canvas 指紋函式庫會檢查這一點,因為它能可靠地區分被修改和未被修改的讀取。即便指令碼無法還原真實雜湊,它現在知道你正在執行畫布保護——而這個知識本身就是一種訊號。在某些分類系統中,「確認為隱私工具使用者」比穩定的雜湊值更有價值,因為它對應的是一個特定的、更小的群體。
除了雙次讀取測試,朴素隨機化還有第二個弱點:雜訊的分佈本身就是工具的指紋。如果你的雜訊是每色版均勻 ±1、採用特定播種演算法,傳回像素的統計特性——均值偏移、變異數、色版相關性——就能識別出具體的擴充套件及其版本。兩個使用相同 CanvasBlocker 版本、相同設定的使用者,其雜訊分量在統計上是相似的,使他們與真實 GPU 差異區別開來,即使底層硬體完全不同。
結構化雜訊:更聰明的替代方案
結構化雜訊用滿足三個屬性的確定性種子替代每次呼叫的隨機性:
- 工作階段內一致。 同一瀏覽器工作階段中對同一畫布的兩次讀取傳回相同的雜訊位元組。雙次讀取測試通過。
- 來源唯一。 在
bank.com上套用的雜訊與在shop.com上不同,因此嵌入在兩個站台的第三方追蹤器無法跨站關聯 Canvas 雜湊。 - 跨工作階段不可預測。 新的瀏覽器工作階段使用新種子,切斷跨工作階段追蹤。
有了這個設計,雙次讀取偵測就會失效。雜訊穩定且內部一致,因此更難與真實的 GPU 級差異區分開來。跨站台和跨工作階段的關聯都被切斷了。
代價是結構化雜訊仍然會暴露有東西在修改 Canvas 輸出。將大量使用者像素陣列與參考值對比的對手可以發現與小型確定性偏移相對應的統計規律——但這需要針對每個受害者確切硬體配置的已知參考值,而遠端伺服器並不具備。
Brave 的 Farbling:運作原理
Brave 的 farbling 是結構化雜訊的生產級實作,直接內建於瀏覽器而非以使用者空間擴充套件的形式提供。這種位置至關重要:因為它在 JavaScript 層之下運作,任何指令碼都無法透過檢查原型鏈或計時 API 來區分 farbling 後的讀取與真實瀏覽器行為。
種子設計實作了結構化雜訊的三個屬性:
- 安裝金鑰。 在安裝時生成一個隨機種子,安全地儲存在瀏覽器設定檔中。除非重置設定檔,否則它不會改變。
- 按來源派生。 安裝金鑰與當前站台 eTLD+1 的雜湊組合,為每個網站生成不同的雜訊配置。即便底層硬體不變,追蹤器在
adnetwork.com上看到的 Canvas 雜湊與在news.com上看到的不同。 - 每工作階段隨機數。 在工作階段開始時混入一個新的隨機值,在每次瀏覽器重新啟動時輪換配置,防止跨工作階段關聯。
像素擾動很小——通常是在隨機選擇的色版上 ±1——使視覺輸出與未修改的算繪無法區分。Brave 同時將 farbling 套用於 WebGL、音訊和其他多個指紋採集面,因此 Canvas 雜訊不會在一個看起來完全正常的訊號集中突顯出來。
Farbling 可以被還原嗎?
還原原始 Canvas 雜湊需要知道受害者確切硬體堆疊——GPU 型號、驅動程式版本、OS 字型引擎和瀏覽器版本——的預期像素值。遠端伺服器無法在沒有實體存取相同硬體的情況下生成這個參考值。跨工作階段平均也不起作用:每工作階段隨機數確保重複造訪產生不同偏移,因此兩次 farbling 讀取的均值並不比任何單次讀取更接近真實雜湊。
然而,farbling 在族群層面並非不可偵測。對大型指紋語料庫的研究表明,Brave 使用者的 Canvas 輸出與普通 Chromium 輸出的聚類方式不同——擾動模式是一個溫和但真實的訊號,表明使用的是 Brave 瀏覽器。你仍然可以被識別為Brave 使用者——一個數千萬而非數十億的群體——但個人層級的追蹤實際上已被打破。EFF 的 Cover Your Tracks 是一個公開工具,可以讓你看到追蹤器實際從你的瀏覽器觀察到什麼,包括你的 Canvas 輸出是否看起來穩定或被隨機化了。
趨同 vs. 隨機化:更深層的權衡
Brave 的 farbling 是目前可用的最佳雜訊實作之一,但它揭示了指紋防禦中的一個結構性張力:隨機化限制了追蹤器能用你的指紋做什麼,而趨同則將指紋作為訊號完全消除。
Tor 瀏覽器採用不同的 Canvas 防禦方式。它為每個使用者傳回一個標準化的近空白值,使所有 Tor 使用者在追蹤器面前看起來一模一樣。沒有雜訊,沒有雜湊變化,沒有統計特徵——只有缺乏有意義的 Canvas 讀取。追蹤器無法得知你的算繪管線資訊,你融入了 Tor 匿名集。代價是更受限制的瀏覽體驗,以及你正在使用 Tor 的訊號。
對於希望在保持正常瀏覽的同時阻斷日常跨站廣告追蹤的使用者,farbling 能很好地實現這一目標。對於需要在高風險場景中保持不可偵測的使用者,趨同是更強的姿態。在 Tor 工作階段中疊加 farbling 實際上可能適得其反,因為這會破壞 Tor 防禦所依賴的趨同性。
Canvas 與 WebGL、音訊和其他訊號如何組合成綜合指紋分數的完整圖景,請參閱我們的 Canvas 指紋偵測指南 和瀏覽器指紋完全解析。
常見問題
追蹤指令碼能否還原雜訊並恢復我的真實 Canvas 雜湊?
實際上不能。恢復真實雜湊需要受害者確切硬體堆疊的參考算繪——GPU 型號、驅動程式版本、OS 字型引擎和瀏覽器版本。遠端伺服器無法生成這個參考值。跨工作階段平均在 Brave 的 farbling 下也無效,因為每工作階段隨機數在每次重新啟動時會改變偏移。
Canvas 雜訊能防護所有指紋採集嗎?
不能。Canvas 只是眾多訊號之一。即便 Canvas 雜訊破壞了 Canvas 雜湊,你的 WebGL 算繪器字串、字型清單、螢幕解析度和音訊指紋仍然不變。能獲取這些其他訊號的追蹤器通常仍然能大幅縮小你的匿名集。
CanvasBlocker 與 Brave 的 farbling 一樣好嗎?
兩者都可以使用結構化雜訊,但 Brave 的實作更難被偵測和繞過:它在 JavaScript API 層之下運作,指令碼無法透過檢查原型鏈來區分它與真實瀏覽器行為。使用者空間擴充套件在 JavaScript 原型層面打補丁,而老練的指令碼可以探測這一層。啟用了結構化雜訊的 CanvasBlocker 比朴素的每次呼叫隨機化或置空要好得多,但並不等同於瀏覽器級保護。
如何檢查我的 Canvas 輸出看起來是帶雜訊還是穩定的?
執行 BrowserInsight 的指紋偵測工具。它會計算你的即時 Canvas 雜湊,顯示該值是否看起來穩定,並估算你的整體指紋相對於常見配置的唯一程度。


