音訊指紋透過 Web Audio API 識別你的裝置,無需麥克風。了解 AudioContext 指紋如何運作,以及如何防範。
音訊指紋是一種透過裝置處理聲音的方式來識別它的追蹤技術——它不靠麥克風錄下任何東西,而是測量你瀏覽器的 Web Audio API 在算繪一段生成訊號時所產生的細微差異。同一段音訊波形,在不同的硬體與軟體堆疊上處理,結果會略有不同,而這種差異足夠穩定,足以協助跨站認出你。本文將說明 AudioContext 指紋如何運作、它的區分度有多高,以及你能採取哪些對策。
核心要點
- 音訊指紋透過測量瀏覽器的 Web Audio API 如何處理一段生成的訊號來識別你的裝置——它從不使用你的麥克風,也不播放任何聲音。
- 整個過程在
OfflineAudioContext之中靜默完成,因此不會出現任何授權彈窗,也不會錄下任何東西。 - 單獨來看它的區分度僅屬中等,但與 Canvas、WebGL 和字型指紋結合時,它會貢獻有意義的資訊熵。
- 清除 Cookie 或使用隱私模式都無法阻止它,因為這個識別碼來自裝置與瀏覽器的特徵,而非儲存的資料。
- 隱私瀏覽器(Firefox、Tor、Brave)與反指紋工具能削弱或隨機化這個訊號,但很少能將其徹底消除。
什麼是音訊指紋?
音訊指紋利用瀏覽器的 Web Audio API 在內部生成一段聲音訊號,讓它流經音訊處理管線,再把數值化的輸出讀回來。關鍵在於:這段聲音從不被播放出來,你的麥克風也從未被觸碰——一切都發生在一個 OfflineAudioContext 之中,它靜默地把結果算繪成一段數字緩衝區。
由於最終的數值取決於你裝置的音訊硬體、作業系統、瀏覽器版本,以及底層的數學函式庫,兩台不同的機器在處理完全相同的輸入時,會產出略有差異的輸出。指令碼會把這些數值雜湊成一段精簡的識別碼。結合 Canvas 與 WebGL 指紋等其他訊號,它便能協助建立一份輪廓,即便你清除了 Cookie 仍能認出你的瀏覽器。
AudioContext 指紋如何運作
這項技術遵循一套可預期的流程:
- 建立離線環境。 指令碼建立一個
OfflineAudioContext,它會以最快速度處理音訊,而不輸出任何聲音。 - 生成訊號。 它建立一個
OscillatorNode(常見為固定頻率的三角波或正弦波),作為一致且可重現的訊號源。 - 處理它。 訊號被導入
DynamicsCompressorNode之類的節點,其浮點運算會放大微小的實作差異。 - 讀回緩衝區。 算繪出的取樣值被加總或雜湊成單一數值。
關鍵的洞見在於:浮點音訊運算在不同系統之間並非逐位元完全一致。儘管 W3C Web Audio API 規範定義了處理圖,卻並未強制要求逐位元一致的輸出,因此不同的 CPU、音訊驅動程式與瀏覽器組建,在取整與處理這些取樣值時方式略有差別。於是最終的雜湊便成了一個裝置與瀏覽器的簽章。
一個簡化的範例
下面的程式碼勾勒了核心概念——生成一個音調、加以壓縮,再把輸出歸結為一個數字:
// 離線算繪一個音調,並將其歸結為一個指紋數值
const ctx = new OfflineAudioContext(1, 44100, 44100);
const oscillator = ctx.createOscillator();
oscillator.type = 'triangle';
oscillator.frequency.value = 10000;
const compressor = ctx.createDynamicsCompressor();
oscillator.connect(compressor);
compressor.connect(ctx.destination);
oscillator.start(0);
ctx.startRendering().then((buffer) => {
const samples = buffer.getChannelData(0);
// 加總一段取樣值;精確的總和會因裝置/瀏覽器而異
let fingerprint = 0;
for (let i = 4000; i < 5000; i++) {
fingerprint += Math.abs(samples[i]);
}
console.log('Audio fingerprint value:', fingerprint);
});
在硬體與版本完全相同的兩個瀏覽器上,結果通常一致;一旦更換作業系統、音訊堆疊或瀏覽器組建,數值便會漂移。
它的區分度與穩定性如何?
音訊指紋的區分度屬於中等——它的唯一識別力不及 WebGL 的 GPU 算繪器字串,但在與其他訊號結合時仍是一項有意義的貢獻。它的行為會因瀏覽器而異:
| 瀏覽器/模式 | 音訊指紋行為 |
|---|---|
| Chrome/Edge(Blink) | 可用且穩定;被追蹤者廣泛使用 |
| Firefox(一般模式) | 可用;Firefox 將其納入指紋防護的標記範圍 |
| Firefox(隱私模式) | 被封鎖或回傳一個中性化的數值 |
| Safari | 可用,但精度受限,因此降低了資訊熵 |
穩定性正是追蹤者在意的特性:一個指紋唯有在多次造訪之間保持不變才有用。對於特定裝置與瀏覽器版本而言,音訊指紋通常是穩定的,不過一次瀏覽器更新可能會讓數值改變。
從資訊理論的角度來看,音訊訊號貢獻的資訊熵並不多——足以縮小一個群體,卻很少足以單憑它就鎖定某一個人。這正是它幾乎從不單獨出現的原因。追蹤者會把音訊的這幾位元,與 WebGL 算繪器字串、已安裝字型、螢幕尺寸與時區等更大的貢獻項結合起來,位元就這樣累加:每個獨立的訊號都會成倍增加可區分組態的數量。音訊之所以能在這套組合中佔有一席之地,正是因為它靜默採集成本低、又相當穩定,因此能可靠地添加位元,而不必跳出授權請求或驚動使用者。
如何防範音訊指紋
你無法讓自己變得完全不可被指紋採集,但可以削弱這個訊號:
- 使用內建防護的瀏覽器。 Firefox 的指紋防護與 Tor 瀏覽器會主動封鎖或正規化音訊指紋。Brave 則按工作階段隨機化其輸出(稱為「farbling」)。
- 擴充功能。 反指紋擴充功能可以為 Web Audio 輸出加入雜訊,不過過於激進的擴充可能會破壞正當的音訊應用程式。
- 理解極限。 單靠無痕/隱私模式並不能阻止指紋採集——它只清除 Cookie 和歷史記錄。音訊指紋無論如何都照常運作,這是一個常見的誤解,我們的瀏覽器指紋指南對此有所說明。
其中的取捨一如往常:更強的防護可能讓網站行為異常,或者——如果你的組態相當罕見——反而讓你更與眾不同(因而更容易被追蹤)。
如何檢測你的音訊指紋
無需撰寫任何程式碼,你就能查看自己的音訊指紋:
- 執行一款指紋檢測工具。 BrowserInsight 的指紋檢測工具會在 Canvas 與 WebGL 之外一併算出你的音訊數值,而 EFF 的 Cover Your Tracks 專案則會展示你整體的瀏覽器組態有多容易被識別。
- 跨瀏覽器對比。 在同一台機器上分別用 Chrome、Firefox 與 Safari 開啟同一項測試。音訊數值通常會因算繪引擎而異,這說明塑造結果的是瀏覽器組建,而不僅僅是硬體。
- 對比一般模式與防護模式。 在開啟嚴格等級「增強型追蹤保護」的 Firefox 中、或在 Tor 瀏覽器中重新執行測試,你會看到音訊數值被封鎖或被歸一化為一個共享的預設值。
影響你所得數值的最關鍵因素歸納如下:
| 參數 | 典型設定 | 為何重要 |
|---|---|---|
| 環境類型 | OfflineAudioContext | 靜默算繪,速度快於實時,且無音訊輸出 |
| 振盪器波形 | 三角波或正弦波 | 一個可重現、確定性的源訊號 |
| 頻率 | 約 10,000 Hz | 固定音調,使得唯一的變化只來自處理過程 |
| 處理節點 | DynamicsCompressorNode | 浮點壓縮會放大微小的實作差異 |
| 被雜湊的取樣範圍 | 緩衝區的一段切片 | 加總或雜湊把數千個取樣值歸結為一個穩定數值 |
由於每個遵循這套流程的指令碼都使用相近的參數,不同站台上的兩個追蹤者就能對同一台裝置得到相近的數值——這恰恰使該訊號能用於跨站識別。
常見問題
音訊指紋會用到我的麥克風嗎?
不會。音訊指紋從不存取你的麥克風,也不播放任何聲音。它透過 Web Audio API 在內部生成一段訊號,並測量你的裝置如何處理它,因此不會出現授權彈窗,也不會錄下任何東西。
我會單靠音訊指紋就被追蹤嗎?
單憑它本身鮮少能做到——它的區分度屬於中等,並非唯一。追蹤者會把它與 Canvas、WebGL、字型及其他訊號結合,建立一份足夠可靠、能認出你的輪廓。音訊只是其中一個貢獻層,而非整個指紋。
清除 Cookie 能阻止音訊指紋嗎?
不能。指紋技術從設計之初就是為了能在清除 Cookie 後存活下來。由於這個識別碼是從你的裝置與瀏覽器特徵中推導出來,而非來自儲存的資料,清除 Cookie 或使用隱私模式都不會改變音訊指紋。
我該如何查看自己的音訊與裝置指紋?
執行 BrowserInsight 的指紋檢測工具,即可看到你的瀏覽器暴露了哪些訊號,包括音訊、Canvas 與 WebGL,以及它們讓你有多容易被識別。
結論
音訊指紋把你瀏覽器靜默的聲音處理轉化成一個穩定的識別碼,全程無需麥克風。單獨來看它的區分度僅屬中等,但作為 Canvas、WebGL 與字型訊號之中的一層,它能協助追蹤者跨站認出你,並在清除 Cookie 後依舊存續。隱私瀏覽器與反指紋工具能削弱它,但務實的目標是降低這個訊號,而非徹底消除它。
推薦閱讀: