(function() { 'use strict'; // Add imperceptible noise to canvas fingerprinting attempts const origToDataURL = HTMLCanvasElement.prototype.toDataURL; const origToBlob = HTMLCanvasElement.prototype.toBlob; const origGetImageData = CanvasRenderingContext2D.prototype.getImageData; function addNoise(ctx, canvas) { try { const w = Math.min(canvas.width, 2); const h = Math.min(canvas.height, 2); const imageData = ctx.getImageData.call(ctx, 0, 0, w, h); // Modify one sub-pixel by ±1 const idx = Math.floor(Math.random() * imageData.data.length); imageData.data[idx] = Math.max(0, Math.min(255, imageData.data[idx] + (Math.random() > 0.5 ? 1 : -1))); ctx.putImageData(imageData, 0, 0); } catch(e) { /* cross-origin or tainted canvas */ } } HTMLCanvasElement.prototype.toDataURL = function() { const ctx = this.getContext('2d'); if (ctx) addNoise(ctx, this); return origToDataURL.apply(this, arguments); }; HTMLCanvasElement.prototype.toBlob = function() { const ctx = this.getContext('2d'); if (ctx) addNoise(ctx, this); return origToBlob.apply(this, arguments); }; CanvasRenderingContext2D.prototype.getImageData = function() { const result = origGetImageData.apply(this, arguments); // Add noise to returned data for fingerprint resistance if (result.data.length > 4) { const idx = Math.floor(Math.random() * result.data.length); result.data[idx] = Math.max(0, Math.min(255, result.data[idx] + (Math.random() > 0.5 ? 1 : -1))); } return result; }; })();