@anonympins/fingerprint 0.1.2 → 0.1.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anonympins/fingerprint",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "An HTTP(S) client mitigation and anti-bot protection library for Node.js/Express, based on digital fingerprinting and dynamic Proof-of-Work (PoW) challenges.",
5
5
  "main": "fingerprint.js",
6
6
  "type": "module",
package/pow.solver.js CHANGED
@@ -16,12 +16,15 @@
16
16
  * @returns {Promise<number>} La solution (un nombre entier).
17
17
  */
18
18
  export async function solveCpuTargetInline(clientIp, nonce, target, clientSecret = null, progressCallback) {
19
- const cpuTarget = BigInt(target);
19
+ // Le 'target' est déjà un BigInt lorsqu'il est appelé depuis la page de challenge.
20
+ // On s'assure juste qu'il est bien de ce type.
21
+ const cpuTarget = typeof target === 'bigint' ? target : BigInt('0x' + target);
20
22
  let cpuSolution = 0;
21
- while (true) {
22
- const msg = clientSecret
23
- ? `${clientIp}:${nonce}:${cpuSolution}:${clientSecret}`
24
- : `${clientIp}:${nonce}:${cpuSolution}`;
23
+ const ipPart = clientIp || ''; // Use empty string if IP is null/undefined
24
+ while (true) { // When a clientSecret is used, the IP is omitted from the hash to make it independent of the network.
25
+ const msg = clientSecret ?
26
+ `${nonce}:${cpuSolution}:${clientSecret}` :
27
+ `${ipPart}:${nonce}:${cpuSolution}`;
25
28
  const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(msg));
26
29
  const hashHex = Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
27
30
  if (BigInt('0x' + hashHex) < cpuTarget) break;
@@ -76,18 +79,28 @@ export async function solveCpuTarget(message, target) {
76
79
  * @returns {Promise<number>} La solution (nombre entier).
77
80
  */
78
81
  export async function solveMemory(seed, difficulty) {
82
+ // On définit un seuil pour savoir quand faire une pause, afin de ne pas bloquer le thread UI.
83
+ const YIELD_THRESHOLD = 100000;
79
84
  const size = difficulty * 1024 * 1024;
80
85
  const buffer = new Uint32Array(size / 4);
81
86
  let h = new TextEncoder().encode(seed).reduce((acc, v) => acc + v, 0);
87
+
82
88
  for (let i = 0; i < buffer.length; i++) {
83
89
  buffer[i] = (h = Math.imul(h ^ i, 1597334677));
90
+ if (i % YIELD_THRESHOLD === 0) {
91
+ await new Promise(r => setTimeout(r, 0)); // Respiration pour ne pas geler l'UI
92
+ }
84
93
  }
94
+
85
95
  let solution = 0;
86
96
  const iterations = size / 16;
87
97
  let addr = buffer.length > 0 ? buffer[0] % buffer.length : 0;
88
98
  for (let i = 0; i < iterations; i++) {
89
99
  addr = buffer[addr] % buffer.length;
90
100
  solution ^= addr;
101
+ if (i % YIELD_THRESHOLD === 0) {
102
+ await new Promise(r => setTimeout(r, 0)); // Respiration pour ne pas geler l'UI
103
+ }
91
104
  }
92
105
  return solution;
93
106
  }
@@ -162,12 +175,16 @@ export async function solveTsp(cities, targetMaxDistance) {
162
175
  * @returns {Promise<object>} Un objet contenant la ou les solutions.
163
176
  */
164
177
  export async function solveChallenge(challenge) {
165
- const { type, nonce, clientSecret, target, memDifficulty, cities, clientIp, targetMaxDistance } = challenge;
178
+ const { type, nonce, clientSecret, cpuTarget, memDifficulty, cities, clientIp, targetMaxDistance } = challenge;
166
179
  const solutions = {};
167
180
 
168
181
  switch (type) {
169
182
  case 'cpu_target':
170
183
  const baseMessageCpu = `:${nonce}`; // L'IP est gérée côté serveur
184
+ if (!cpuTarget) {
185
+ throw new Error("Challenge data is missing 'cpuTarget' property.");
186
+ }
187
+ const target = cpuTarget; // Keep variable name for consistency below
171
188
  solutions.cpu = await solveCpuTarget(baseMessageCpu, BigInt('0x' + target));
172
189
  break;
173
190
  case 'cpu_mem':
@@ -175,8 +192,10 @@ export async function solveChallenge(challenge) {
175
192
  const baseMessageCombined = `${nonce}:${clientSecret}`;
176
193
  const memSeed = `:${nonce}:${clientSecret}`;
177
194
  const [cpuSol, memSol] = await Promise.all([
178
- // On utilise une version de solveCpuTarget qui n'a pas besoin de l'IP
179
- solveCpuTargetInline(null, nonce, target, clientSecret),
195
+ (async () => {
196
+ if (!cpuTarget) throw new Error("Challenge data is missing 'cpuTarget' property.");
197
+ return solveCpuTargetInline(null, nonce, cpuTarget, clientSecret);
198
+ })(),
180
199
  solveMemory(memSeed, memDifficulty)
181
200
  ]);
182
201
  solutions.cpu = cpuSol;
@@ -186,7 +205,10 @@ export async function solveChallenge(challenge) {
186
205
  // Version inline pour compatibilité HTML avec IP incluse
187
206
  const memSeedInline = `${nonce}:${clientSecret}`;
188
207
  const [cpuSolInline, memSolInline] = await Promise.all([
189
- solveCpuTargetInline(clientIp, nonce, target, clientSecret),
208
+ (async () => {
209
+ if (!cpuTarget) throw new Error("Challenge data is missing 'cpuTarget' property.");
210
+ return solveCpuTargetInline(clientIp, nonce, cpuTarget, clientSecret);
211
+ })(),
190
212
  solveMemory(memSeedInline, memDifficulty)
191
213
  ]);
192
214
  solutions.cpu = cpuSolInline;