音频指纹无需麦克风,仅凭 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 后依然有效。隐私浏览器和反指纹工具能削弱它,但务实的目标是降低这个信号,而非彻底消除它。
推荐阅读: