一段听不见的声音,为什么能认出你
打开网页时,你多半不会想到浏览器正在"算声音"。但很多识别脚本确实会这么做:它们用 AudioContext 在内存里合成一小段音频,让它流过振荡器、压缩器这类处理节点,再把输出的数值读出来。整个过程不经过扬声器,你听不到,也不会收到任何提示。
关键在于,这段音频在不同设备上跑出来的结果不完全一样。音频信号从生成到被读出,会经过一条由浏览器、操作系统、底层数学库乃至硬件共同决定的处理链路。不同的实现对浮点运算的取舍、对信号的微小处理差异,会让最终数值在小数点后若干位上出现偏差。脚本把这些数值拼起来做一次哈希,就得到一串看起来平平无奇、却相当稳定的标识——这就是音频指纹。
它的"杀伤力"来自两点:一是稳定,同一台设备多次计算结果基本一致;二是无感,用户全程不知情,也无从拒绝。
和 Canvas、WebGL 指纹是一家人
如果你听说过 Canvas 指纹或 WebGL 指纹,那么音频指纹的套路会很熟悉,它们本质上是同一类手法:让浏览器做一件标准化的事,再去量不同设备结果上的细微差别。
- Canvas 指纹:让浏览器绘制同一段文字或图形,读取像素,差异来自字体渲染和图形栈。
- WebGL 指纹:渲染同一个 3D 场景,差异来自显卡与驱动。
- 音频指纹:处理同一段音频信号,差异来自音频处理链路。
三者维度不同,却共享一个假设:同样的输入,不同设备会给出可区分的输出。正因为同源,它们常常被一起采集、交叉比对——单看一维也许不够独特,几维叠加就足以把你和别人区分开。
真正的风险:绕过 Cookie 的跨站追踪
音频指纹讨厌的地方,在于它不依赖 Cookie。你清掉 Cookie、开隐私模式,甚至换个网站,指纹往往还是那一个。于是它能被用来:
- 跨站识别:不同网站采集到同一指纹,就能把你在各处的浏览轨迹串起来。
- 绕过常规清理:删 Cookie、换标签页都不影响,用户几乎没有有效的对抗手段。
- 关联多账号:对需要同时运营多个账号的人来说,这是最头疼的一点——哪怕换了登录信息,相同的指纹仍可能把这些账号判定为"同一个人、同一台设备"。
换句话说,音频指纹是一把能悄悄穿过常规隐私设置的"暗钥匙"。
怎么防才算防到点上
很多人第一反应是直接禁用或每次都给随机值。但这两招往往适得其反。
正常设备总会有一个稳定且合理的音频指纹。如果某个环境干脆读不出音频数据,或者每次刷新结果都在剧烈跳变,这种"异常"本身就是一种更扎眼的信号——反而容易被判定为自动化或刻意伪装。
更稳妥的思路是加噪:在音频数据里引入细微而可控的扰动,让指纹看起来真实、数值稳定,同时又和其他环境彼此独立。也就是说,同一个环境自己多次计算要一致,不同环境之间要各不相同,像一台台真实存在的独立设备。
还有容易被忽视的一点:指纹从来不是孤立的一维。音频、Canvas、WebGL、时区、语言、字体等参数需要整套自洽。只改音频、其他维度却对不上,拼在一起照样露馅。
在这件事上,虎鲸的做法是对 AudioContext 音频指纹采用噪声处理:每个环境的扰动独立且自洽,保持稳定;并且把 Canvas、WebGL、音频等多个维度一并纳入,做跨维度的自洽校验,尽量让每个环境呈现为一台可信的独立设备。具体防护效果仍以官方说明为准。
小结
音频指纹是一种听不见、点不着、却实实在在存在的追踪手段,它和 Canvas、WebGL 指纹同根同源,共同构成了跨站识别与多账号关联的隐形网。理解它的原理,才能明白为什么"全禁用""全随机"都不是答案——真正的关键,是让每个环境既稳定又独立,并且整套参数自洽。