Chrome 上的画布指纹识别
Posted
技术标签:
【中文标题】Chrome 上的画布指纹识别【英文标题】:Canvas Fingerprinting on Chrome 【发布时间】:2014-10-19 23:09:15 【问题描述】:我一直在尝试使用Canvas Fingerprinting 为我的数据库提供另一层用户识别...我知道经验丰富的黑客可以绕过这一层,因为指纹是在客户端创建的,但是,嘿,越多安全层越好,对吧?
不幸的是,我为 Google Chrome 测试指纹的每台 Windows 7 计算机都会产生相同的指纹。例如,转到这个 jsfiddle:http://jsfiddle.net/af1pL6fb/5/ 我使用过的所有 Win7/Chrome 机器的哈希值都是 503251348。如果这么多不同的用户得到相同的哈希值,指纹就没有用了。
我尝试在画布上绘制各种随机的东西,以使每台计算机产生略微不同的结果 - 正如理论一样 - 但我尝试的所有方法都让每个 Chrome 浏览器都给出相同的结果。
当其他计算机的其他相同浏览器给我不同的结果(如预期的那样)时,任何人都知道为什么 Chrome 会有这样的行为吗?
或者有人知道我可以在画布中加入一些东西来鼓励不同的结果吗?
或者有人知道我可以用来区分计算机的不同指标吗?例如,我将 navigator.mimeType 数组视为一种为特定浏览器提供半唯一指示器的潜在方式。
这是我的指纹功能:
function fingerprint()
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var txt = 'i9asdm..$#po((^@KbXrww!~cz';
ctx.textBaseline = "top";
ctx.font = "16px 'Arial'";
ctx.textBaseline = "alphabetic";
ctx.rotate(.05);
ctx.fillStyle = "#f60";
ctx.fillRect(125,1,62,20);
ctx.fillStyle = "#069";
ctx.fillText(txt, 2, 15);
ctx.fillStyle = "rgba(102, 200, 0, 0.7)";
ctx.fillText(txt, 4, 17);
ctx.shadowBlur=10;
ctx.shadowColor="blue";
ctx.fillRect(-20,10,234,5);
var strng=canvas.toDataURL();
var hash=0;
if (strng.length==0) return;
for (i = 0; i < strng.length; i++)
char = strng.charCodeAt(i);
hash = ((hash<<5)-hash)+char;
hash = hash & hash;
return hash;
【问题讨论】:
如果你希望指纹不同,每次调用fingerprint()
时txt
不应该不同,而不是硬编码?我在 chrome 和 FF 上测试了你的小提琴,hash
在两者上总是相同的(看看你的代码是有道理的,因为我不希望 strng
有所不同)。
不,画布指纹识别的工作方式是为所有用户绘制完全相同的图像,但每个浏览器/计算机绘制图像的方式略有不同。因此,如果您将该图像转换为数据,您最终会得到一个每个浏览器唯一的字符串——即使每个浏览器都被告知要绘制完全相同的东西。
这很奇怪。我在您的链接中得到了相同的哈希值。我昨天开始搞砸这个,我做的第一件事就是得到fingerprint.js,因为我知道我的尝试充其量是愚蠢的。您can visit my site 它将为同一台计算机上的每个浏览器生成不同的指纹。不知道为什么 Chrome 总是会生成相同的指纹,因为谷歌现在使用它来跟踪我们。
我还在某处读到,在使用 PNG 而不是 JPG 将画布编码为 BASE64 后,您可以使用 CRC 位。也许这就是为什么您每次都得到相同结果的原因,因为它使用了一些廉价的 JPEG 压缩。
【参考方案1】:
有一个名为 fingerprint.js 的库似乎运行良好。
它将为非 html 5 客户端获取指纹 启用画布将在可用时提高准确性 如果启用,它可以根据浏览器上安装的插件创建更独特的指纹(虽然不确定为什么需要它)我已经在我的网站上嵌入了这个脚本,并 you can get fingerprinted here 进行测试。它在同一浏览器上以隐身模式工作,而 Chrome 在其他计算机上的指纹识别方式不同。
我将尝试处理业务逻辑,以尝试将指纹与同一个人联系起来。显然,在像我这样请求很少但值得一试的死站点上,这很困难。
您可以尝试在 PNG 上使用 32 位 CRC 作为described on this site。 IE atob。
var b64 = canvas.toDataURL.replace("data:image/png;base64,","");
var bin = atob(b64);
// crc32 takes only 4 bytes and placed from 16 to 12 byte from the end of file
var crc = bin2hex(bin.slice(-16,-12));
我的签名是 FE72FC19 基于该方法。
【讨论】:
我的原始代码基于 finterprint.js。我删除了所有基于屏幕分辨率和用户代理等其他因素生成指纹的代码。随着新显示器的插入或浏览器的更新,我可以很容易地看到随着时间的推移而发生的变化。我将尝试您描述的 PNG 操作。如果它依赖计算机的图形芯片来形成 PNG,我可以看到它如何产生更独特的标识符。 好吧,我注意到今天我去了我的网站,我有了一个新的标识符......我确实安装了一个插件(但没有在插件中启用它)但没有其他任何改变:(思考以上是关于Chrome 上的画布指纹识别的主要内容,如果未能解决你的问题,请参考以下文章
新闻Firefox 58将阻止基于画布的浏览器指纹识别,以停止在线跟踪
-webkit-overflow-scrolling:在 chrome 和 ios 上无法识别触摸