字型指紋透過你裝置上安裝的字型來識別你。了解字型列舉與量測如何運作,以及如何減少你的暴露。
字型指紋透過你裝置上安裝的那組字型來識別它。你所擁有的字型組合——由作業系統、已安裝軟體、語言包與設計工具共同塑造——區分度出奇地高,而網站無需任何特殊授權,就能從 JavaScript 偵測出這個組合。本文將說明字型列舉與量測如何運作、為什麼結果如此具有識別性,以及如何減少你所洩漏的資訊。
核心要點
- 並沒有無需授權就能列出你字型的 API;追蹤者透過算繪文字,並量測當所請求的字型缺失時瀏覽器如何替換為後備字型來推斷它們。
- 幾百次「存在/不存在」的探測組合起來,便構成一份高資訊熵的輪廓,因為字型組合反映了你的作業系統、已安裝應用程式與語言包。
- 該技術無需任何授權,且能在清除 Cookie 或使用隱私模式後依然存活,因為它源自算繪行為,而非儲存的資料。
- 較新的
queryLocalFonts()API 雖能列出真實字型,卻被一個明確的授權彈窗所限制,因此並非追蹤者所仰賴的隱蔽手段。 - 最好的防禦是趨同:像 Tor 瀏覽器這樣的瀏覽器會把可見字型組合標準化,讓所有人看起來都一樣,而不是加入自訂字型。
什麼是字型指紋?
字型指紋的做法,是判定你系統上安裝了哪些字型,並把這份清單當作裝置識別碼的一部分。你的字型組合通常不是你會留意的東西,卻攜帶著真實的資訊熵:一台預設安裝的 Windows、一台裝了 Adobe 應用程式的 Mac,以及一台裝有開發工具的 Linux 機器,所攜帶的字型集合明顯各不相同。
網站無法直接問「你有哪些字型?」——並沒有一個能回傳完整清單的直接 API。它們改為透過測試特定字型、並觀察文字如何算繪來推斷。與 Canvas 和音訊指紋一樣,它仰賴的是可量測的算繪差異,而非儲存的資料,因此能在清除 Cookie 後存活下來。諸如 EFF 的 Cover Your Tracks 這類隱私研究工具,正展示了這些被動訊號在組合之後是多麼具有區分度。
字型偵測如何運作
經典的技術是後備字型量測。當瀏覽器被要求以一種未安裝的字型算繪文字時,它會悄悄替換成一種預設字型——而這個替代字型的字母尺寸幾乎總是不同。透過量測這些尺寸,指令碼便能判斷所請求的字型是否確實存在。
這個方法的運作流程如下:
- 量測基準。 以已知的通用字型(
monospace、sans-serif、serif)算繪一段測試字串,並記錄精確的寬度與高度。 - 請求候選字型。 以相同字串請求某個特定字型(例如「Calibri」),並指定一個通用字型作為後備。
- 比較。 若尺寸與後備字型的基準不同,代表該候選字型已安裝;若與後備字型相符,則代表未安裝。
- 重複。 對一份數百種常見字型的清單逐一執行,建立一份「存在/不存在」的輪廓。
// 透過後備字型量測偵測某個特定字型是否已安裝
function isFontInstalled(font) {
const baseFont = 'monospace';
const text = 'mmmmmmmmmmlli';
const span = document.createElement('span');
span.style.fontSize = '72px';
span.style.position = 'absolute';
span.style.left = '-9999px';
span.textContent = text;
document.body.appendChild(span);
span.style.fontFamily = baseFont;
const baseWidth = span.offsetWidth;
// 請求候選字型,並以基準字型作為後備
span.style.fontFamily = `'${font}', ${baseFont}`;
const testWidth = span.offsetWidth;
document.body.removeChild(span);
return testWidth !== baseWidth; // 寬度不同 => 字型存在
}
較新的變體會使用 Canvas API 來更精確地量測文字。指令碼不再讀取元素的方框尺寸,而是用 measureText() 把測試字串繪製到畫布上,並檢查回傳的字形度量——即便兩種字型恰好擁有相同的前進寬度,這些度量也可能不同,從而讓偵測更可靠、更難被粗糙的防禦所欺騙。
列舉與 Local Font Access API 的區別
把兩種截然不同的能力區分開會有所幫助:
| 方式 | 授權 | 揭露的內容 |
|---|---|---|
| 後備/畫布量測 | 無需 | 你專門探測的每一種字型的存在或不存在,一次一種 |
queryLocalFonts() | 明確彈窗 | 已安裝字型的完整清單,包括 PostScript 名稱與字型家族名稱 |
第一種方式只能就指令碼已想到要測試的字型回答「這種字型安裝了嗎?」,因此追蹤者會附帶一份精心整理的、包含數百種常見字型家族的清單。第二種——即 Chromium 系瀏覽器中提供的 Local Font Access API——只需一次呼叫即可回傳完整的本機字型組合,但前提是使用者授予了 local-fonts 權限。由於該彈窗醒目且容易被拒絕,隱蔽的追蹤者很少使用它;無聲的後備量測方法依然是字型指紋的主力。
為什麼你的字型清單如此具有識別性
字型組合是從許多來源累積而來的,而這種多樣性正是它對追蹤如此有用的原因:
- 作業系統與版本隨附不同的預設字型。
- 已安裝的應用程式——Microsoft Office、Adobe Creative Cloud 與設計工具——會加入具有區分度的字型家族。
- 語言與地區包會加入許多系統所缺乏的文字系統(CJK、西里爾文、阿拉伯文)。
- 手動安裝的字型——來自設計師與開發者——具有高度的個別性。
每一個「安裝與否」的答案都是一個位元的資訊熵,而幾百次探測組合起來,便能形成一份足以單獨鎖定許多使用者的輪廓——尤其是在與其他訊號結合時。
字型指紋如何融入更大的圖像
字型指紋鮮少單獨運作。它是一整套堆疊中的一層,其中還包括 Canvas、WebGL、音訊、螢幕參數與 User-Agent 資料。它與瀏覽器附加元件也有所重疊:某些擴充功能會注入自己的字型或改變字型行為,這反而可能讓你更容易被識別,而非更難。理解整體圖像正是我們瀏覽器指紋指南的重點所在。
如何降低你的字型指紋
- 使用會限制字型列舉的瀏覽器。 Tor 瀏覽器把網站能用的字型限制在一組標準集合內,讓所有人看起來都一樣;Firefox 的抗指紋模式也有類似作用。Brave 則套用隨機化。
- 避免安裝罕見字型於你用來進行隱私敏感瀏覽的瀏覽器設定檔中——你的字型組合越罕見,你就越獨特。
- 對注入字型的擴充功能保持警惕,它們可能擴大你可被偵測到的字型清單。
- 了解極限。 與其他技術一樣,無痕/隱私模式無法阻止字型指紋;它只清除 Cookie 和歷史記錄。
這個反直覺的教訓是:趨同才能保護你——目標是讓自己看起來和大家一樣,而不是加入更多客製字型。
最強的防禦實際如何運作
最有效的工具與其說是隱藏你的字型,不如說是抹平使用者之間的差異:
- 標準化。 Tor 瀏覽器附帶一套固定的字型包,並告訴網頁只存在這些字型,無論實際安裝了什麼。因此每一位 Tor 使用者都回報相同的字型組合,把這個訊號的資訊熵壓縮到接近於零。Firefox 的
privacy.resistFingerprinting模式秉持同樣的理念。 - 隨機化。 Brave 會對量測值施加輕微且按工作階段變化的擾動,使得重複探測無法回傳穩定的答案。這會破壞讓指紋變得有用的跨造訪可關聯性,即便單次快照看起來仍然合理。
- 縮減你的暴露面。 在加固型瀏覽器之外,請為隱私敏感的瀏覽保留一個乾淨的設定檔:避免安裝罕見的字型家族,並移除注入字型的擴充功能。一台原裝的作業系統遠不如一台裝滿設計軟體的系統那樣獨特。
沒有任何單一開關能消除字型指紋,把加固型瀏覽器與精簡的字型組合結合起來才是現實的目標。至於更宏觀的威脅模型——字型如何與其他訊號組合——W3C 在其 Web 平台指南中將指紋技術記載為一項公認的隱私關切。
常見問題
網站能直接看到我安裝的所有字型嗎?
未經授權則不行。並沒有一個無需授權、能列出每一種字型的 API。網站透過算繪文字並量測後備字型替換來推斷你的字型,這會一次一個字型地揭露其存在與否。較新的 queryLocalFonts() API 雖能列出字型,但需要明確的授權彈窗。
字型指紋需要任何授權嗎?
不需要。後備字型量測法使用的是普通的文字算繪與元素尺寸量測,這些都不需要授權,也不會觸發任何彈窗。這正是它對追蹤者如此有吸引力、又讓使用者難以察覺的原因。
清除 Cookie 會移除我的字型指紋嗎?
不會。這個指紋是從你安裝了哪些字型推導出來的,而非來自儲存的資料,因此清除 Cookie 或使用隱私模式都不會改變它。要降低它,必須在瀏覽器層級限制字型列舉。
我該如何查看瀏覽器暴露了什麼?
執行 BrowserInsight 的指紋檢測工具,查看你的瀏覽器洩漏了哪些訊號,並執行外掛與擴充偵測工具,檢視可能影響你字型輪廓的附加元件。
結論
字型指紋讀取你系統累積而成的那組獨特字型,並把它轉化成一個穩定的識別碼——無需授權、無需麥克風、無需儲存資料。由於字型組合反映了你的作業系統、應用程式與使用習慣,它攜帶著真實的資訊熵,尤其在與 Canvas、WebGL 與音訊訊號並列時更是如此。有效的防禦不是加入更多字型,而是融入人群:使用一個能標準化或隨機化字型列舉的瀏覽器,並讓你的隱私設定檔保持平凡。
推薦閱讀: