Skip to content

Instantly share code, notes, and snippets.

@mike-at-redspace
Created March 5, 2023 11:29
Show Gist options
  • Save mike-at-redspace/3e17bb344f6030f22a09ec13f9eac2c9 to your computer and use it in GitHub Desktop.
Save mike-at-redspace/3e17bb344f6030f22a09ec13f9eac2c9 to your computer and use it in GitHub Desktop.
getCanvasFingerprint
import sha256 from 'crypto-js/sha256';
import Regl from 'regl';
const signals = {
pixelRatio: window.devicePixelRatio || 1,
userAgent: window.navigator.userAgent,
language: window.navigator.language,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
screenWidth: window.screen.width,
screenHeight: window.screen.height,
availScreenWidth: window.screen.availWidth,
availScreenHeight: window.screen.availHeight,
touchSupport: 'ontouchstart' in window || navigator.msMaxTouchPoints > 0,
cookieEnabled: navigator.cookieEnabled,
localStorageEnabled: (() => {
try {
localStorage.setItem('test', 'test');
localStorage.removeItem('test');
return true;
} catch (e) {
return false;
}
})(),
sessionStorageEnabled: (() => {
try {
sessionStorage.setItem('test', 'test');
sessionStorage.removeItem('test');
return true;
} catch (e) {
return false;
}
})(),
doNotTrack: navigator.doNotTrack,
plugins: (() => {
if (navigator.plugins) {
return Array.from(navigator.plugins).map((plugin) => plugin.name);
}
return null;
})(),
fonts: (() => {
const fonts = [];
const container = document.createElement('span');
container.style.fontSize = '72px';
container.innerHTML = 'abcdefghijklmnopqrstuvwxyz0123456789';
const defaultWidth = container.offsetWidth;
const defaultHeight = container.offsetHeight;
const fontList = [
'monospace',
'serif',
'sans-serif',
'cursive',
'fantasy',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'Segoe UI',
];
fontList.forEach((font) => {
container.style.fontFamily = font;
const width = container.offsetWidth;
const height = container.offsetHeight;
if (width !== defaultWidth || height !== defaultHeight) {
fonts.push(font);
}
});
return fonts.length ? fonts : null;
})(),
};
function getCanvasFingerprint() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 200;
canvas.height = 200;
let hash = '';
try {
const regl = Regl(canvas);
const drawCircle = regl({
frag: `
precision mediump float;
varying vec4 color;
void main() {
gl_FragColor = color;
}
`,
vert: `
precision mediump float;
attribute vec2 position;
attribute vec4 color;
varying vec4 vColor;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
vColor = color;
}
`,
attributes: {
position: [
[-1, -1],
[1, -1],
[1, 1],
[-1, 1],
],
color: [
[1, 0, 0, 1],
[0, 1, 0, 1],
[0, 0, 1, 1],
[1, 1, 1, 1],
],
},
elements: [
[0, 1, 2],
[0, 2, 3],
],
});
drawCircle();
const drawGradient = regl({
frag: `
precision mediump float;
varying vec2 uv;
void main() {
gl_FragColor = vec4(uv, 0.0, 1.0);
}
`,
vert: `
precision mediump float;
attribute vec2 position;
varying vec2 uv;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
uv = position * 0.5 + 0.5;
}
`,
attributes: {
position: [
[-1, -1],
[1, -1],
[1, 1],
[-1, 1],
],
},
elements: [
[0, 1, 2],
[0, 2, 3],
],
});
drawGradient();
const dataURL = canvas.toDataURL();
hash = sha256(dataURL + JSON.stringify(signals)).toString();
} catch (e) {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.font = "20px sans-serif";
ctx.fillText("Hello, world!", 50, 50);
const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
gradient.addColorStop(0, "red");
gradient.addColorStop(1, "blue");
ctx.fillStyle = gradient;
const dataURL = canvas.toDataURL();
hash = sha256(dataURL + JSON.stringify(signals)).toString();
}
return hash;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment