UNPKG

dprintjs

Version:

Generate unique device fingerprints using browser characteristics

1 lines 14.5 kB
{"version":3,"file":"index.cjs","sources":["../src/fingerprint.service.ts"],"sourcesContent":["// src/fingerprint.service.ts\nexport interface FingerprintOptions {\n format?: 'short' | 'long';\n includeCanvas?: boolean;\n includeAudio?: boolean;\n includeWebGL?: boolean;\n salt?: string; // Optional salt for additional randomness\n}\n\nexport class dPrintId {\n private static _instance: dPrintId;\n\n private constructor() {}\n\n public static getInstance(): dPrintId {\n if (!dPrintId._instance) {\n dPrintId._instance = new dPrintId();\n }\n return dPrintId._instance;\n }\n\n public async generateFingerprint(options: FingerprintOptions = {}): Promise<string> {\n const components = await this.collectComponents(options);\n \n if (options.format === 'long') {\n return this.generateLongFingerprint(components, options.salt);\n }\n \n return this.generateShortFingerprint(components, options.salt);\n }\n\n private async collectComponents(options: FingerprintOptions): Promise<string[]> {\n const components: string[] = [];\n\n try {\n // Basic components (always included)\n components.push(navigator.userAgent);\n components.push(`${window.screen.height}x${window.screen.width}x${window.screen.colorDepth}`);\n components.push(Intl.DateTimeFormat().resolvedOptions().timeZone);\n components.push(navigator.language);\n components.push(navigator.hardwareConcurrency?.toString() || '');\n components.push((navigator as any).deviceMemory?.toString() || '');\n components.push(navigator.platform);\n\n // Optional components\n if (options.includeCanvas !== false) {\n const canvasData = await this.getCanvasFingerprint();\n components.push(canvasData);\n }\n\n if (options.includeAudio !== false) {\n const audioData = await this.getAudioFingerprint();\n components.push(audioData);\n }\n\n if (options.includeWebGL !== false) {\n const webglData = this.getWebGLFingerprint();\n components.push(webglData);\n }\n\n // Add some additional entropy\n components.push(new Date().getTimezoneOffset().toString());\n components.push(this.getPlugins());\n components.push(this.getTouchSupport());\n \n } catch (error) {\n console.warn('Error collecting fingerprint components:', error);\n }\n\n return components;\n }\n\n private async getCanvasFingerprint(): Promise<string> {\n try {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (!ctx) return '';\n\n canvas.width = 200;\n canvas.height = 50;\n\n // Add a background\n ctx.fillStyle = '#f60';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.fillStyle = '#069';\n ctx.fillRect(2, 2, 50, 50);\n\n // Add text\n ctx.textBaseline = 'top';\n ctx.font = '14px Arial';\n ctx.fillStyle = '#069';\n ctx.fillText('👋 Hello, world!', 4, 15);\n\n // Add some shapes\n ctx.strokeStyle = '#069';\n ctx.beginPath();\n ctx.moveTo(100, 10);\n ctx.bezierCurveTo(120, 20, 140, 0, 160, 30);\n ctx.stroke();\n\n return canvas.toDataURL();\n } catch {\n return '';\n }\n }\n\n private async getAudioFingerprint(): Promise<string> {\n try {\n const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();\n const oscillator = audioContext.createOscillator();\n const analyser = audioContext.createAnalyser();\n const gainNode = audioContext.createGain();\n const scriptProcessor = audioContext.createScriptProcessor(4096, 1, 1);\n\n gainNode.gain.value = 0;\n oscillator.type = 'triangle';\n oscillator.connect(analyser);\n analyser.connect(scriptProcessor);\n scriptProcessor.connect(gainNode);\n gainNode.connect(audioContext.destination);\n\n oscillator.start(0);\n\n const audioTimeData = new Float32Array(analyser.frequencyBinCount);\n analyser.getFloatFrequencyData(audioTimeData);\n\n oscillator.stop();\n audioContext.close();\n\n return Array.from(audioTimeData)\n .slice(0, 5)\n .map(x => x.toString())\n .join(',');\n } catch {\n return '';\n }\n }\n\n private getWebGLFingerprint(): string {\n try {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n if (!gl) return '';\n\n const webgl = gl as WebGLRenderingContext;\n\n const data = [\n webgl.getParameter(webgl.VENDOR),\n webgl.getParameter(webgl.RENDERER),\n webgl.getParameter(webgl.VERSION),\n webgl.getParameter(webgl.SHADING_LANGUAGE_VERSION),\n this.getWebGLExtensions(webgl),\n ].join('~');\n\n return data;\n } catch {\n return '';\n }\n }\n\n private getWebGLExtensions(gl: WebGLRenderingContext): string {\n try {\n const extensions = gl.getSupportedExtensions();\n return extensions ? extensions.join(',') : '';\n } catch {\n return '';\n }\n }\n\n private getPlugins(): string {\n try {\n const plugins = Array.from(navigator.plugins || [])\n .map(p => [p.name, p.description, Array.from(p)])\n .flat()\n .join(',');\n return plugins;\n } catch {\n return '';\n }\n }\n\n private getTouchSupport(): string {\n try {\n const touchPoints = navigator.maxTouchPoints;\n const touchEvent = 'ontouchstart' in window;\n const touchList = 'TouchEvent' in window;\n \n return `${touchPoints},${touchEvent},${touchList}`;\n } catch {\n return '';\n }\n }\n\n private async generateLongFingerprint(components: string[], salt?: string): Promise<string> {\n try {\n const data = components.join('|||') + (salt || '');\n const msgBuffer = new TextEncoder().encode(data);\n const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n } catch {\n // Fallback to short fingerprint if crypto API is not available\n return this.generateShortFingerprint(components, salt);\n }\n }\n\n private generateShortFingerprint(components: string[], salt?: string): string {\n const data = components.join('|||') + (salt || '');\n let h1 = 0xdeadbeef;\n let h2 = 0x41c6ce57;\n\n for (let i = 0; i < data.length; i++) {\n const ch = data.charCodeAt(i);\n h1 = Math.imul(h1 ^ ch, 2654435761);\n h2 = Math.imul(h2 ^ ch, 1597334677);\n }\n\n h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);\n h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);\n h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\n // Generate 8-character string\n return (h2 >>> 0).toString(36).padStart(6, '0') + \n (h1 >>> 0).toString(36).padStart(6, '0').slice(0, 2);\n }\n}"],"names":[],"mappings":";;MASa,QAAQ,CAAA;AAGnB,IAAA,WAAA,GAAA,GAAwB;AAEjB,IAAA,OAAO,WAAW,GAAA;AACvB,QAAA,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE;AACvB,YAAA,QAAQ,CAAC,SAAS,GAAG,IAAI,QAAQ,EAAE,CAAC;SACrC;QACD,OAAO,QAAQ,CAAC,SAAS,CAAC;KAC3B;AAEM,IAAA,MAAM,mBAAmB,CAAC,OAAA,GAA8B,EAAE,EAAA;QAC/D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;AAEzD,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE;YAC7B,OAAO,IAAI,CAAC,uBAAuB,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;SAC/D;QAED,OAAO,IAAI,CAAC,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;KAChE;IAEO,MAAM,iBAAiB,CAAC,OAA2B,EAAA;QACzD,MAAM,UAAU,GAAa,EAAE,CAAC;AAEhC,QAAA,IAAI;;AAEF,YAAA,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YACrC,UAAU,CAAC,IAAI,CAAC,CAAA,EAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAI,CAAA,EAAA,MAAM,CAAC,MAAM,CAAC,KAAK,CAAA,CAAA,EAAI,MAAM,CAAC,MAAM,CAAC,UAAU,CAAE,CAAA,CAAC,CAAC;AAC9F,YAAA,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC,CAAC;AAClE,YAAA,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AACpC,YAAA,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,mBAAmB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AACjE,YAAA,UAAU,CAAC,IAAI,CAAE,SAAiB,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AACnE,YAAA,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;;AAGpC,YAAA,IAAI,OAAO,CAAC,aAAa,KAAK,KAAK,EAAE;AACnC,gBAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;AACrD,gBAAA,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;aAC7B;AAED,YAAA,IAAI,OAAO,CAAC,YAAY,KAAK,KAAK,EAAE;AAClC,gBAAA,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;AACnD,gBAAA,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aAC5B;AAED,YAAA,IAAI,OAAO,CAAC,YAAY,KAAK,KAAK,EAAE;AAClC,gBAAA,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;AAC7C,gBAAA,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aAC5B;;AAGD,YAAA,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,iBAAiB,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC3D,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACnC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;SAEzC;QAAC,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,IAAI,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;SACjE;AAED,QAAA,OAAO,UAAU,CAAC;KACnB;AAEO,IAAA,MAAM,oBAAoB,GAAA;AAChC,QAAA,IAAI;YACF,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAChD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACpC,YAAA,IAAI,CAAC,GAAG;AAAE,gBAAA,OAAO,EAAE,CAAC;AAEpB,YAAA,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC;AACnB,YAAA,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;;AAGnB,YAAA,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC;AACvB,YAAA,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;AAChD,YAAA,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC;YACvB,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;;AAG3B,YAAA,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC;AACzB,YAAA,GAAG,CAAC,IAAI,GAAG,YAAY,CAAC;AACxB,YAAA,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC;YACvB,GAAG,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;;AAGxC,YAAA,GAAG,CAAC,WAAW,GAAG,MAAM,CAAC;YACzB,GAAG,CAAC,SAAS,EAAE,CAAC;AAChB,YAAA,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACpB,YAAA,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YAC5C,GAAG,CAAC,MAAM,EAAE,CAAC;AAEb,YAAA,OAAO,MAAM,CAAC,SAAS,EAAE,CAAC;SAC3B;AAAC,QAAA,MAAM;AACN,YAAA,OAAO,EAAE,CAAC;SACX;KACF;AAEO,IAAA,MAAM,mBAAmB,GAAA;AAC/B,QAAA,IAAI;AACF,YAAA,MAAM,YAAY,GAAG,KAAK,MAAM,CAAC,YAAY,IAAK,MAAc,CAAC,kBAAkB,GAAG,CAAC;AACvF,YAAA,MAAM,UAAU,GAAG,YAAY,CAAC,gBAAgB,EAAE,CAAC;AACnD,YAAA,MAAM,QAAQ,GAAG,YAAY,CAAC,cAAc,EAAE,CAAC;AAC/C,YAAA,MAAM,QAAQ,GAAG,YAAY,CAAC,UAAU,EAAE,CAAC;AAC3C,YAAA,MAAM,eAAe,GAAG,YAAY,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAEvE,YAAA,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;AACxB,YAAA,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC;AAC7B,YAAA,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC7B,YAAA,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;AAClC,YAAA,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAClC,YAAA,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;AAE3C,YAAA,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAEpB,MAAM,aAAa,GAAG,IAAI,YAAY,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AACnE,YAAA,QAAQ,CAAC,qBAAqB,CAAC,aAAa,CAAC,CAAC;YAE9C,UAAU,CAAC,IAAI,EAAE,CAAC;YAClB,YAAY,CAAC,KAAK,EAAE,CAAC;AAErB,YAAA,OAAO,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC;AAC7B,iBAAA,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;iBACX,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;iBACtB,IAAI,CAAC,GAAG,CAAC,CAAC;SACd;AAAC,QAAA,MAAM;AACN,YAAA,OAAO,EAAE,CAAC;SACX;KACF;IAEO,mBAAmB,GAAA;AACzB,QAAA,IAAI;YACF,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;AAChD,YAAA,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AACjF,YAAA,IAAI,CAAC,EAAE;AAAE,gBAAA,OAAO,EAAE,CAAC;YAEnB,MAAM,KAAK,GAAG,EAA2B,CAAC;AAE1C,YAAA,MAAM,IAAI,GAAG;AACX,gBAAA,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC;AAChC,gBAAA,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC;AAClC,gBAAA,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC;AACjC,gBAAA,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,wBAAwB,CAAC;AAClD,gBAAA,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;AAC/B,aAAA,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,YAAA,OAAO,IAAI,CAAC;SACb;AAAC,QAAA,MAAM;AACN,YAAA,OAAO,EAAE,CAAC;SACX;KACF;AAEO,IAAA,kBAAkB,CAAC,EAAyB,EAAA;AAClD,QAAA,IAAI;AACF,YAAA,MAAM,UAAU,GAAG,EAAE,CAAC,sBAAsB,EAAE,CAAC;AAC/C,YAAA,OAAO,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;SAC/C;AAAC,QAAA,MAAM;AACN,YAAA,OAAO,EAAE,CAAC;SACX;KACF;IAEO,UAAU,GAAA;AAChB,QAAA,IAAI;YACF,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAC;iBAChD,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,iBAAA,IAAI,EAAE;iBACN,IAAI,CAAC,GAAG,CAAC,CAAC;AACb,YAAA,OAAO,OAAO,CAAC;SAChB;AAAC,QAAA,MAAM;AACN,YAAA,OAAO,EAAE,CAAC;SACX;KACF;IAEO,eAAe,GAAA;AACrB,QAAA,IAAI;AACF,YAAA,MAAM,WAAW,GAAG,SAAS,CAAC,cAAc,CAAC;AAC7C,YAAA,MAAM,UAAU,GAAG,cAAc,IAAI,MAAM,CAAC;AAC5C,YAAA,MAAM,SAAS,GAAG,YAAY,IAAI,MAAM,CAAC;AAEzC,YAAA,OAAO,GAAG,WAAW,CAAA,CAAA,EAAI,UAAU,CAAI,CAAA,EAAA,SAAS,EAAE,CAAC;SACpD;AAAC,QAAA,MAAM;AACN,YAAA,OAAO,EAAE,CAAC;SACX;KACF;AAEO,IAAA,MAAM,uBAAuB,CAAC,UAAoB,EAAE,IAAa,EAAA;AACvE,QAAA,IAAI;AACF,YAAA,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACjD,YAAA,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACpE,YAAA,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;YACzD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SACrE;AAAC,QAAA,MAAM;;YAEN,OAAO,IAAI,CAAC,wBAAwB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;SACxD;KACF;IAEO,wBAAwB,CAAC,UAAoB,EAAE,IAAa,EAAA;AAClE,QAAA,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;QACnD,IAAI,EAAE,GAAG,UAAU,CAAC;QACpB,IAAI,EAAE,GAAG,UAAU,CAAC;AAEpB,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACpC,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC9B,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;YACpC,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;SACrC;AAED,QAAA,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;AAC7C,QAAA,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;AAC9C,QAAA,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;AAC7C,QAAA,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;;AAG9C,QAAA,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;YACxC,CAAC,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KAC7D;AACF;;;;"}