@cloudglides/veil 0.1.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/index.d.ts +103 -0
  2. package/dist/index.js +1000 -0
  3. package/dist/veil_core_bg.wasm +0 -0
  4. package/package.json +24 -10
  5. package/.envrc +0 -1
  6. package/.github/workflows/build-on-tag.yml +0 -82
  7. package/.github/workflows/deploy-pages.yml +0 -73
  8. package/example/index.html +0 -220
  9. package/example/veil_core.d.ts +0 -71
  10. package/example/veil_core_bg.wasm +0 -0
  11. package/example/veil_core_bg.wasm.d.ts +0 -20
  12. package/flake.nix +0 -68
  13. package/scripts/patch-wasm.js +0 -12
  14. package/src/cpu.ts +0 -67
  15. package/src/entropy/adblock.ts +0 -16
  16. package/src/entropy/approximate.ts +0 -9
  17. package/src/entropy/audio.ts +0 -17
  18. package/src/entropy/battery.ts +0 -10
  19. package/src/entropy/browser.ts +0 -7
  20. package/src/entropy/canvas.ts +0 -17
  21. package/src/entropy/complexity.ts +0 -14
  22. package/src/entropy/connection.ts +0 -14
  23. package/src/entropy/distribution.ts +0 -9
  24. package/src/entropy/fonts.ts +0 -4
  25. package/src/entropy/hardware.ts +0 -10
  26. package/src/entropy/language.ts +0 -14
  27. package/src/entropy/os.ts +0 -12
  28. package/src/entropy/osVersion.ts +0 -6
  29. package/src/entropy/performance.ts +0 -14
  30. package/src/entropy/permissions.ts +0 -15
  31. package/src/entropy/plugins.ts +0 -14
  32. package/src/entropy/preferences.ts +0 -12
  33. package/src/entropy/probabilistic.ts +0 -20
  34. package/src/entropy/screen.ts +0 -12
  35. package/src/entropy/screenInfo.ts +0 -8
  36. package/src/entropy/spectral.ts +0 -9
  37. package/src/entropy/statistical.ts +0 -15
  38. package/src/entropy/storage.ts +0 -22
  39. package/src/entropy/timezone.ts +0 -10
  40. package/src/entropy/userAgent.ts +0 -16
  41. package/src/entropy/webFeatures.ts +0 -21
  42. package/src/entropy/webgl.ts +0 -11
  43. package/src/gpu.ts +0 -132
  44. package/src/index.test.ts +0 -26
  45. package/src/index.ts +0 -248
  46. package/src/normalize/index.ts +0 -31
  47. package/src/probability.ts +0 -11
  48. package/src/scoring.ts +0 -106
  49. package/src/seeded-rng.ts +0 -14
  50. package/src/stability.ts +0 -405
  51. package/src/tamper.ts +0 -207
  52. package/src/types/index.ts +0 -11
  53. package/src/types.ts +0 -56
  54. package/src/veil_core.d.ts +0 -4
  55. package/src/wasm-loader.ts +0 -44
  56. package/tsconfig.json +0 -12
  57. package/tsup.config.ts +0 -41
  58. package/veil-core/Cargo.lock +0 -114
  59. package/veil-core/Cargo.toml +0 -12
  60. package/veil-core/src/entropy.rs +0 -132
  61. package/veil-core/src/lib.rs +0 -93
  62. package/veil-core/src/similarity.rs +0 -67
  63. package/vitest.config.ts +0 -15
  64. /package/{example → dist}/veil_core.js +0 -0
package/src/stability.ts DELETED
@@ -1,405 +0,0 @@
1
- import type { EntropySource } from "./scoring";
2
-
3
- export interface SourceStability {
4
- source: string;
5
- stability: number;
6
- volatility: number;
7
- category: "stable" | "semi_volatile" | "volatile";
8
- }
9
-
10
- export interface EntropyWarning {
11
- source: string;
12
- severity: "info" | "warning" | "error";
13
- message: string;
14
- reason: string;
15
- }
16
-
17
- export interface DeviceSignature {
18
- os: string;
19
- hardware_cores: number;
20
- screen_resolution: string;
21
- user_agent_hash: string;
22
- }
23
-
24
- export interface PreferencesOffset {
25
- theme: string | null;
26
- language: string | null;
27
- timezone: string | null;
28
- font_size: string | null;
29
- dark_mode: boolean | null;
30
- accessibility: string | null;
31
- }
32
-
33
- export interface DeviceIdentity {
34
- core_hash: string;
35
- device_signature: DeviceSignature;
36
- entropy_quality: number;
37
- preferences_offset: PreferencesOffset;
38
- preferences_hash: string;
39
- }
40
-
41
- export interface FingerprintDrift {
42
- overall_similarity: number;
43
- drift_detected: boolean;
44
- changed_sources: Array<{
45
- name: string;
46
- previous: string;
47
- current: string;
48
- critical: boolean;
49
- }>;
50
- stability_breakdown: SourceStability[];
51
- }
52
-
53
- const STABILITY_THRESHOLDS = {
54
- stable: 0.85,
55
- semi_volatile: 0.5,
56
- };
57
-
58
- export function getSourceStability(sources: EntropySource[]): SourceStability[] {
59
- const stabilityMap: Record<string, number> = {
60
- userAgent: 0.95,
61
- os: 0.95,
62
- timezone: 0.98,
63
- hardware: 0.9,
64
- language: 0.92,
65
- screen: 0.88,
66
- osVersion: 0.85,
67
- browser: 0.93,
68
- canvas: 0.82,
69
- webgl: 0.8,
70
- fonts: 0.7,
71
- plugins: 0.75,
72
- storage: 0.5,
73
- adblock: 0.65,
74
- screenInfo: 0.85,
75
- webFeatures: 0.8,
76
- permissions: 0.6,
77
- preferences: 0.55,
78
- statistical: 0.7,
79
- probabilistic: 0.65,
80
- distribution: 0.75,
81
- complexity: 0.8,
82
- spectral: 0.75,
83
- approximate: 0.75,
84
- connection: 0.4,
85
- battery: 0.3,
86
- audio: 0.85,
87
- performance: 0.2,
88
- };
89
-
90
- return sources.map((source) => {
91
- const stability = stabilityMap[source.name] ?? 0.5;
92
- const volatility = 1 - stability;
93
-
94
- let category: "stable" | "semi_volatile" | "volatile";
95
- if (stability >= STABILITY_THRESHOLDS.stable) {
96
- category = "stable";
97
- } else if (stability >= STABILITY_THRESHOLDS.semi_volatile) {
98
- category = "semi_volatile";
99
- } else {
100
- category = "volatile";
101
- }
102
-
103
- return {
104
- source: source.name,
105
- stability,
106
- volatility,
107
- category,
108
- };
109
- });
110
- }
111
-
112
- export function detectFingerprintDrift(
113
- previousFingerprint: { hash: string; sources: Array<{ source: string; value: string; critical?: boolean }> },
114
- currentSources: EntropySource[],
115
- ): FingerprintDrift {
116
- const changed_sources: FingerprintDrift["changed_sources"] = [];
117
- let changeCount = 0;
118
-
119
- const criticalSources = new Set(["userAgent", "canvas", "webgl", "screen"]);
120
-
121
- for (const currentSource of currentSources) {
122
- const previousSource = previousFingerprint.sources.find(
123
- (s) => s.source === currentSource.name,
124
- );
125
-
126
- if (!previousSource) {
127
- changed_sources.push({
128
- name: currentSource.name,
129
- previous: "N/A",
130
- current: currentSource.value,
131
- critical: criticalSources.has(currentSource.name),
132
- });
133
- changeCount++;
134
- } else if (previousSource.value !== currentSource.value) {
135
- changed_sources.push({
136
- name: currentSource.name,
137
- previous: previousSource.value,
138
- current: currentSource.value,
139
- critical: criticalSources.has(currentSource.name),
140
- });
141
- changeCount++;
142
- }
143
- }
144
-
145
- const stability_breakdown = getSourceStability(currentSources);
146
-
147
- const criticalChanges = changed_sources.filter((c) => c.critical).length;
148
- const volatileSources = stability_breakdown.filter(
149
- (s) => s.category === "volatile",
150
- ).length;
151
-
152
- const expectedChanges = volatileSources * 0.5;
153
- const drift_detected = criticalChanges > 0 || changeCount > expectedChanges + 3;
154
-
155
- const overall_similarity = Math.max(
156
- 0,
157
- 1 - (changeCount / currentSources.length) * 0.5,
158
- );
159
-
160
- return {
161
- overall_similarity,
162
- drift_detected,
163
- changed_sources,
164
- stability_breakdown,
165
- };
166
- }
167
-
168
- function hashString(str: string): string {
169
- let hash = 0;
170
- for (let i = 0; i < str.length; i++) {
171
- const char = str.charCodeAt(i);
172
- hash = ((hash << 5) - hash) + char;
173
- hash = hash & hash;
174
- }
175
- return Math.abs(hash).toString(16);
176
- }
177
-
178
- export function detectEntropyAnomalies(sources: EntropySource[]): EntropyWarning[] {
179
- const warnings: EntropyWarning[] = [];
180
- const sourceMap = new Map(sources.map((s) => [s.name, s]));
181
-
182
- for (const source of sources) {
183
- const value = source.value.toLowerCase();
184
-
185
- if (!value || value.length === 0) {
186
- warnings.push({
187
- source: source.name,
188
- severity: "error",
189
- message: "Empty entropy value",
190
- reason: "Source returned no data, likely blocked or unavailable API",
191
- });
192
- }
193
-
194
- if (/^(null|undefined|nan|n\/a|-1|0x0|unknown|not available|blocked)$/i.test(value)) {
195
- warnings.push({
196
- source: source.name,
197
- severity: "error",
198
- message: "Suspicious placeholder value detected",
199
- reason: "Value appears to be a default/placeholder, not real entropy",
200
- });
201
- }
202
-
203
- if (source.entropy === 0 && value.length > 2) {
204
- warnings.push({
205
- source: source.name,
206
- severity: "warning",
207
- message: "Zero entropy despite non-empty value",
208
- reason: "Value is highly repetitive or contains minimal information",
209
- });
210
- }
211
-
212
- if (source.entropy > 8 && value.length < 5) {
213
- warnings.push({
214
- source: source.name,
215
- severity: "warning",
216
- message: "Suspiciously high entropy in very short value",
217
- reason: "Short strings cannot contain this much entropy mathematically",
218
- });
219
- }
220
-
221
- if (source.name === "canvas" || source.name === "webgl") {
222
- if (value.length < 10) {
223
- warnings.push({
224
- source: source.name,
225
- severity: "warning",
226
- message: "Graphics fingerprint is unusually short",
227
- reason: "Canvas/WebGL fingerprints should contain detailed rendering info",
228
- });
229
- }
230
- }
231
-
232
- if (source.name === "fonts") {
233
- if (value === "0" || value === "[]" || value.split(",").length < 3) {
234
- warnings.push({
235
- source: source.name,
236
- severity: "warning",
237
- message: "Suspiciously few fonts detected",
238
- reason: "System should report 50+ fonts; low count suggests API blocking",
239
- });
240
- }
241
- }
242
-
243
- if (source.name === "screen") {
244
- const match = value.match(/(\d+)x(\d+)/);
245
- if (match) {
246
- const [w, h] = [parseInt(match[1]), parseInt(match[2])];
247
- if (w < 320 || h < 240 || w > 7680 || h > 4320) {
248
- warnings.push({
249
- source: source.name,
250
- severity: "warning",
251
- message: "Unusual screen resolution detected",
252
- reason: `Resolution ${w}x${h} is outside normal range`,
253
- });
254
- }
255
- }
256
- }
257
-
258
- if (source.name === "userAgent") {
259
- const isCommonUA = /chrome|firefox|safari|edge|mozilla/i.test(value);
260
- if (!isCommonUA && value.length > 10) {
261
- warnings.push({
262
- source: source.name,
263
- severity: "info",
264
- message: "Unusual user agent detected",
265
- reason: "User agent does not match known browsers",
266
- });
267
- }
268
- }
269
- }
270
-
271
- if (sources.length > 0) {
272
- const avgEntropy = sources.reduce((a, b) => a + b.entropy, 0) / sources.length;
273
- if (avgEntropy < 0.3) {
274
- warnings.push({
275
- source: "_system",
276
- severity: "warning",
277
- message: "Overall entropy is very low",
278
- reason: "Average entropy across sources is below 0.3, fingerprint may be unreliable",
279
- });
280
- }
281
- }
282
-
283
- return warnings;
284
- }
285
-
286
- export function extractDeviceSignature(sources: EntropySource[]): DeviceSignature {
287
- const osSource = sources.find((s) => s.name === "os");
288
- const hardwareSource = sources.find((s) => s.name === "hardware");
289
- const screenSource = sources.find((s) => s.name === "screen");
290
- const uaSource = sources.find((s) => s.name === "userAgent");
291
-
292
- const os = osSource?.value.split("|")[0] ?? "unknown";
293
- const hardwareStr = hardwareSource?.value ?? "0";
294
- const cores = parseInt(hardwareStr.match(/\d+/)?.[0] ?? "0");
295
- const resolution = screenSource?.value ?? "0x0";
296
- const uaHash = uaSource ? hashString(uaSource.value) : "0";
297
-
298
- return {
299
- os,
300
- hardware_cores: cores,
301
- screen_resolution: resolution,
302
- user_agent_hash: uaHash,
303
- };
304
- }
305
-
306
- function extractPreferencesOffset(sources: EntropySource[]): PreferencesOffset {
307
- const langSource = sources.find((s) => s.name === "language");
308
- const tzSource = sources.find((s) => s.name === "timezone");
309
- const prefSource = sources.find((s) => s.name === "preferences");
310
-
311
- let theme: string | null = null;
312
- let dark_mode: boolean | null = null;
313
- let accessibility: string | null = null;
314
-
315
- if (prefSource && prefSource.value) {
316
- const parts = prefSource.value.split("|");
317
- if (parts.length > 0) dark_mode = parts[0] === "true";
318
- if (parts.length > 1) theme = parts[1];
319
- if (parts.length > 2) accessibility = parts[2];
320
- }
321
-
322
- return {
323
- language: langSource ? langSource.value.split("|")[0] : null,
324
- timezone: tzSource ? tzSource.value.split("|")[0] : null,
325
- theme,
326
- dark_mode,
327
- font_size: null,
328
- accessibility,
329
- };
330
- }
331
-
332
- export function generateDeviceIdentity(sources: EntropySource[]): DeviceIdentity {
333
- const signature = extractDeviceSignature(sources);
334
- const signatureStr = `${signature.os}|${signature.hardware_cores}|${signature.screen_resolution}|${signature.user_agent_hash}`;
335
- const coreHash = hashString(signatureStr);
336
-
337
- const preferences = extractPreferencesOffset(sources);
338
- const prefsStr = `${preferences.language}|${preferences.timezone}|${preferences.theme}|${preferences.dark_mode}|${preferences.accessibility}`;
339
- const prefsHash = hashString(prefsStr);
340
-
341
- const qualityScore =
342
- sources.filter((s) => s.entropy > 0.5).length / Math.max(sources.length, 1);
343
-
344
- return {
345
- core_hash: coreHash,
346
- device_signature: signature,
347
- entropy_quality: qualityScore,
348
- preferences_offset: preferences,
349
- preferences_hash: prefsHash,
350
- };
351
- }
352
-
353
- export function assessFingerprint(
354
- sources: EntropySource[],
355
- ): {
356
- usable: boolean;
357
- confidence: number;
358
- warnings: string[];
359
- entropy_warnings: EntropyWarning[];
360
- } {
361
- const stability = getSourceStability(sources);
362
- const entropyWarnings = detectEntropyAnomalies(sources);
363
- const warnings: string[] = [];
364
- let usable = true;
365
- let confidence = 1;
366
-
367
- const stableCount = stability.filter((s) => s.category === "stable").length;
368
- const volatileCount = stability.filter((s) => s.category === "volatile").length;
369
-
370
- if (stableCount < 5) {
371
- warnings.push(
372
- `Only ${stableCount} stable sources available, fingerprint may be unreliable`,
373
- );
374
- confidence -= 0.2;
375
- }
376
-
377
- if (volatileCount > sources.length * 0.5) {
378
- warnings.push("Fingerprint heavily dependent on volatile sources");
379
- confidence -= 0.15;
380
- }
381
-
382
- const zeroEntropyCount = sources.filter((s) => s.entropy === 0).length;
383
- if (zeroEntropyCount > sources.length * 0.3) {
384
- warnings.push(`${zeroEntropyCount} sources have zero entropy`);
385
- confidence -= 0.25;
386
- if (zeroEntropyCount > sources.length * 0.6) {
387
- usable = false;
388
- }
389
- }
390
-
391
- const errorWarnings = entropyWarnings.filter((w) => w.severity === "error").length;
392
- if (errorWarnings > sources.length * 0.2) {
393
- confidence -= 0.2;
394
- if (errorWarnings > sources.length * 0.4) {
395
- usable = false;
396
- }
397
- }
398
-
399
- return {
400
- usable,
401
- confidence: Math.max(0, confidence),
402
- warnings,
403
- entropy_warnings: entropyWarnings,
404
- };
405
- }
package/src/tamper.ts DELETED
@@ -1,207 +0,0 @@
1
- import type { EntropySource } from "./scoring";
2
-
3
- export type AnomalySeverity = "low" | "medium" | "high" | "critical";
4
- export type AnomalyCategory =
5
- | "entropy_distribution"
6
- | "missing_sources"
7
- | "value_spoofing"
8
- | "cross_source_inconsistency"
9
- | "data_quality";
10
-
11
- export interface Anomaly {
12
- id: string;
13
- category: AnomalyCategory;
14
- severity: AnomalySeverity;
15
- message: string;
16
- explanation: string;
17
- riskContribution: number;
18
- }
19
-
20
- export interface TamperAnalysis {
21
- tampering_risk: number;
22
- anomalies: Anomaly[];
23
- }
24
-
25
- export function analyzeTamper(sources: EntropySource[]): TamperAnalysis {
26
- const anomalies: Anomaly[] = [];
27
- let riskScore = 0;
28
-
29
- if (sources.length === 0) {
30
- anomalies.push({
31
- id: "no_sources",
32
- category: "missing_sources",
33
- severity: "critical",
34
- message: "No entropy sources collected",
35
- explanation:
36
- "The fingerprinting process failed to collect any entropy data. This may indicate a sandbox environment or blocked APIs.",
37
- riskContribution: 0.9,
38
- });
39
- return { tampering_risk: 0.9, anomalies };
40
- }
41
-
42
- const entropies = sources.map((s) => s.entropy);
43
- const values = sources.map((s) => s.value);
44
-
45
- const mean = entropies.reduce((a, b) => a + b, 0) / entropies.length;
46
- const variance =
47
- entropies.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / entropies.length;
48
- const stdDev = Math.sqrt(variance);
49
-
50
- if (stdDev < 0.05) {
51
- const contribution = 0.25;
52
- anomalies.push({
53
- id: "uniform_entropy",
54
- category: "entropy_distribution",
55
- severity: "high",
56
- message: "All entropy sources have suspiciously similar values",
57
- explanation: `Standard deviation of entropy across sources is ${stdDev.toFixed(4)}, indicating very low variance. Real fingerprints should show diverse entropy patterns.`,
58
- riskContribution: contribution,
59
- });
60
- riskScore += contribution;
61
- }
62
-
63
- const uniqueValues = new Set(values);
64
- if (uniqueValues.size < sources.length * 0.5) {
65
- const contribution = 0.2;
66
- const duplicateCount = sources.length - uniqueValues.size;
67
- anomalies.push({
68
- id: "duplicate_values",
69
- category: "data_quality",
70
- severity: "medium",
71
- message: `${duplicateCount} duplicate values detected across entropy sources`,
72
- explanation:
73
- "High duplication suggests cached or placeholder values. Expected diversity is not present.",
74
- riskContribution: contribution,
75
- });
76
- riskScore += contribution;
77
- }
78
-
79
- const emptyOrShort = values.filter((v) => !v || v.length < 2).length;
80
- if (emptyOrShort > sources.length * 0.3) {
81
- const contribution = 0.15;
82
- anomalies.push({
83
- id: "empty_sources",
84
- category: "data_quality",
85
- severity: "high",
86
- message: `${emptyOrShort} sources are empty or too short`,
87
- explanation:
88
- "Several entropy sources produced minimal data. This may indicate blocked APIs or restricted environment.",
89
- riskContribution: contribution,
90
- });
91
- riskScore += contribution;
92
- }
93
-
94
- const sourceNames = sources.map((s) => s.name);
95
- const criticalSources = ["userAgent", "canvas", "webgl", "fonts"];
96
- const missingCritical = criticalSources.filter(
97
- (c) => !sourceNames.includes(c),
98
- );
99
-
100
- if (missingCritical.length > 0) {
101
- const contribution =
102
- 0.2 * (missingCritical.length / criticalSources.length);
103
- anomalies.push({
104
- id: "missing_critical",
105
- category: "missing_sources",
106
- severity:
107
- missingCritical.length === criticalSources.length ? "critical" : "high",
108
- message: `Missing critical sources: ${missingCritical.join(", ")}`,
109
- explanation:
110
- "These sources are fundamental to browser fingerprinting. Their absence reduces fingerprint reliability and suggests API restrictions or tampering.",
111
- riskContribution: contribution,
112
- });
113
- riskScore += contribution;
114
- }
115
-
116
- const canvasSource = sources.find((s) => s.name === "canvas");
117
- const webglSource = sources.find((s) => s.name === "webgl");
118
-
119
- if (
120
- canvasSource &&
121
- webglSource &&
122
- canvasSource.value === webglSource.value &&
123
- canvasSource.entropy < 0.5
124
- ) {
125
- const contribution = 0.15;
126
- anomalies.push({
127
- id: "canvas_webgl_match",
128
- category: "cross_source_inconsistency",
129
- severity: "high",
130
- message: "Canvas and WebGL fingerprints are identical",
131
- explanation:
132
- "Canvas and WebGL rendering engines should produce different fingerprints. Identical values indicate either spoofing or a very unusual environment.",
133
- riskContribution: contribution,
134
- });
135
- riskScore += contribution;
136
- }
137
-
138
- const screenSource = sources.find((s) => s.name === "screen");
139
- if (screenSource && screenSource.value.length < 3) {
140
- const contribution = 0.1;
141
- anomalies.push({
142
- id: "screen_entropy_low",
143
- category: "data_quality",
144
- severity: "low",
145
- message: "Screen entropy data is suspiciously minimal",
146
- explanation:
147
- "Screen information should provide resolution and color depth data. Very short values suggest incomplete data collection.",
148
- riskContribution: contribution,
149
- });
150
- riskScore += contribution;
151
- }
152
-
153
- const maxEntropy = Math.max(...entropies);
154
- const minEntropy = Math.min(...entropies);
155
- if (maxEntropy > 0 && minEntropy / maxEntropy < 0.1) {
156
- const contribution = 0.15;
157
- anomalies.push({
158
- id: "entropy_variance",
159
- category: "entropy_distribution",
160
- severity: "medium",
161
- message: `Extreme variance in entropy: min/max ratio is ${(minEntropy / maxEntropy).toFixed(3)}`,
162
- explanation:
163
- "Some sources have drastically different entropy levels, suggesting uneven data collection or selective API blocking.",
164
- riskContribution: contribution,
165
- });
166
- riskScore += contribution;
167
- }
168
-
169
- const zeroEntropyCount = entropies.filter((e) => e === 0).length;
170
- if (zeroEntropyCount > sources.length * 0.4) {
171
- const contribution = 0.1;
172
- anomalies.push({
173
- id: "zero_entropy",
174
- category: "data_quality",
175
- severity: "medium",
176
- message: `${zeroEntropyCount} sources have zero entropy`,
177
- explanation:
178
- "Zero entropy typically means identical or highly repetitive data. Many sources with zero entropy suggests a restricted or heavily spoofed environment.",
179
- riskContribution: contribution,
180
- });
181
- riskScore += contribution;
182
- }
183
-
184
- const suspiciousPatterns = sources.filter((s) =>
185
- /^(null|undefined|test|fake|mock)$/i.test(s.value),
186
- );
187
- if (suspiciousPatterns.length > 0) {
188
- const contribution = 0.2;
189
- anomalies.push({
190
- id: "placeholder_values",
191
- category: "value_spoofing",
192
- severity: "critical",
193
- message: `Placeholder values detected: ${suspiciousPatterns.map((s) => s.name).join(", ")}`,
194
- explanation:
195
- "Sources contain obvious placeholder/test values (null, undefined, fake, mock). This is a strong indicator of intentional spoofing.",
196
- riskContribution: contribution,
197
- });
198
- riskScore += contribution;
199
- }
200
-
201
- const finalRisk = Math.min(riskScore, 1);
202
-
203
- return {
204
- tampering_risk: finalRisk,
205
- anomalies,
206
- };
207
- }
@@ -1,11 +0,0 @@
1
- export interface FingerprintOptions {
2
- entropy: {
3
- userAgent?: boolean;
4
- canvas?: boolean;
5
- webgl?: boolean;
6
- fonts?: boolean;
7
- storage?: boolean;
8
- screen?: boolean;
9
- };
10
- hash?: "sha256" | "sha512";
11
- }
package/src/types.ts DELETED
@@ -1,56 +0,0 @@
1
- export interface FingerprintOptions {
2
- entropy: {
3
- userAgent?: boolean;
4
- canvas?: boolean;
5
- webgl?: boolean;
6
- fonts?: boolean;
7
- storage?: boolean;
8
- screen?: boolean;
9
- };
10
- hash?: "sha256" | "sha512";
11
- detailed?: boolean;
12
- }
13
-
14
- export interface SourceMetric {
15
- source: string;
16
- value: string;
17
- entropy: number;
18
- confidence: number;
19
- stability?: number;
20
- }
21
-
22
- import type { Anomaly } from "./tamper";
23
- import type { EntropyWarning, DeviceIdentity } from "./stability";
24
-
25
- export interface FingerprintResponse {
26
- hash: string;
27
- uniqueness: number;
28
- confidence: number;
29
- stability_score?: number;
30
- usable: boolean;
31
- warnings?: string[];
32
- entropy_warnings?: EntropyWarning[];
33
- tampering_risk: number;
34
- anomalies: Anomaly[];
35
- device_identity?: DeviceIdentity;
36
- sources: SourceMetric[];
37
- system: {
38
- os: string;
39
- language: string;
40
- timezone: string;
41
- hardware: {
42
- cores: number;
43
- memory: number;
44
- };
45
- };
46
- display: {
47
- resolution: string;
48
- colorDepth: number;
49
- devicePixelRatio: number;
50
- };
51
- browser: {
52
- userAgent: string;
53
- vendor: string;
54
- cookieEnabled: boolean;
55
- };
56
- }
@@ -1,4 +0,0 @@
1
- export function fnv_hash(s: string): string;
2
- export function kolmogorov_complexity(s: string): number;
3
- export function murmur_hash(s: string): string;
4
- export function shannon_entropy(s: string): number;