browser-canvas-fingerprinting
Version:
A simple canvas fingerprinting implementation in browser with specific information used to generate fingerprint
52 lines (51 loc) • 4.24 kB
JavaScript
import getFonts from './font.js';
import { getWebGLInfo, createWebGLFingerprint } from './webgl.js';
import { keyCount } from './util.js';
import { isExtensionFuckingCanvas } from './detection.js';
export default async function data() {
function getErrorMessage(f, useStack = false) {
try { return f() } catch (e) { return (useStack ? e.stack : String(e)) }
}
async function getErrorMessageAsync(f, useStack = false) {
try { return await f() } catch (e) { return (useStack ? e.stack : String(e)) }
}
function causeRefError() {
const rand = Math.random().toString().substring(2);
return getErrorMessage(() => (new Function('a' + rand))()).replace(rand, '<R>');
}
function causeTypeError() {
const rand = Math.random().toString().substring(2);
return getErrorMessage(() => globalThis[rand]["//"].b).replace(rand, '<R>');
}
function purifyConcurrency() {
const value = globalThis.navigator.hardwareConcurrency;
if (!value || (value % 2)) return 'N/A';
return value; // but still useless when fighting with JShelter...
}
const isExt = await isExtensionFuckingCanvas();
const { vendor, renderer } = getWebGLInfo();
return [
`Emojis: \u{1F601}\u{1F602}\u{1F603}\u{1F604}\u{1F60C}\u{1F60F}\u{1F612}\u{1F621}\u{1F631}\u{1F628}`,
`Special chars (Unicode): \u2060\u200B\u25CF\u25CB\u25D0\u25D1\u25D2\u25D3\u2605\u2606\u2724\u2726\u2736\u2737\u272A\u272B\u272F\u2730\u2742\u25C6\u25C8\u25B6\u25C0\u25B2\u25BC\u25BA\u25C4\u27A4\u27A5\u27A1\u27A2\u2740\u273F\u2741\u273E\u2668\u266A\u266B\u2669\u2704\u2702\u2701\u2706\u2709\u2756\u2726\u2727\u221E\u2763\u2765\u2719\u271A\u271C\u271B\u2020\u2021`,
`Zalgo: \u0334\u0322\u031B\u031B\u0317\u0318Z\u0337\u034C\u035D\u030B\u0310\u0344\u030C\u0344\u035D\u0313\u0346\u0344\u035D\u033F\u030F\u035D\u033F\u035D\u035D\u030F\u033F\u030F\u035D\u033F\u035D\u030F\u033F\u035Da\u0335\u031B\u030C\u0344\u035D\u033F\u030F\u035D\u033F\u035D\u030F\u033F\u035Dl\u0336\u034C\u035D\u030B\u0310\u0344\u030C\u0344\u035D\u0313\u0346\u0344\u035D\u033F\u030F\u035D\u033Fg\u0337\u034C\u035D\u030B\u0310\u0344\u030C\u0344\u035D\u0313\u0346\u0344\u035D\u033F\u030F\u035D\u033Fo\u0334\u0322\u031B\u031B\u0317\u0318 \u0334\u0322\u031B\u031B\u0317\u0318T\u0337\u034C\u035D\u030B\u0310\u0344\u030C\u0344\u035D\u0313\u0346\u0344\u035D\u033F\u030F\u035D\u033Fe\u0335\u031B\u030C\u0344\u035D\u033F\u030F\u035D\u033F\u035D\u030F\u033F\u035Dx\u0336\u034C\u035D\u030B\u0310\u0344\u030C\u0344\u035D\u0313\u0346\u0344\u035D\u033F\u030F\u035D\u033Ft\u0337\u034C\u035D\u030B\u0310\u0344\u030C\u0344\u035D\u0313\u0346\u0344\u035D\u033F\u030F\u035D\u033F`,
`User-Agent: ${globalThis.navigator.userAgent}`,
`Platform: ${globalThis.navigator.platform}`,
`Languages: ${globalThis.navigator.languages}`,
`Cookies enabled: ${globalThis.navigator.cookieEnabled}`,
`Navigator properties count: ${keyCount(globalThis.navigator)}`,
`Timezone: ${getErrorMessage(() => globalThis.Intl.DateTimeFormat().resolvedOptions().timeZone)}`,
`Fonts: ${getFonts()}`,
`Hardware Concurrency: ${isExt ? 'Ignored due to extension activity' : purifyConcurrency()}`,
`Plugins: ${navigator.plugins ? (Array.from(navigator.plugins).map(p => p.name).join(', ')) : 'unknown'}`,
`Screen: ${screen.width}x${screen.height}, Depth: ${screen.colorDepth}bit`,
`Available Screen: ${screen.availWidth}x${screen.availHeight}`,
`Max Touch Points: ${isExt ? 'Ignored due to extension activity' : globalThis.navigator.maxTouchPoints}`,
`WebGL Vendor: ${vendor}`,
`WebGL Renderer: ${renderer}`,
`WebGL Fingerprint: ${await createWebGLFingerprint()}`,
`Support navigation API: ${globalThis.navigation}`,
`Support WebXR API: ${globalThis.navigator.xr}`,
`Support WebGPU API: ${globalThis.navigator.gpu}`,
`Browser error message: ${causeTypeError()};${causeRefError()};${getErrorMessage(() => customElements.define())};${getErrorMessage(() => new Function("';|+_<"))};${await getErrorMessageAsync(() => crypto.subtle.encrypt())};${getErrorMessage(() => structuredClone(globalThis))}`,
];
}