@anonympins/fingerprint 0.6.6 → 0.6.7
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/CHANGELOG.md +16 -0
- package/README.md +15 -2
- package/package.json +1 -1
- package/public/fp.js +1 -1
- package/public/fp.wasm +0 -0
- package/src/js/fingerprint.client.obfuscated.js +1 -1
- package/src/js/fingerprint.js +27 -9
- package/src/js/problem-manager.js +10 -3
- package/src/js/tests/fingerprint.engine.test.js +25 -0
- package/src/js/tests/fingerprint.test.js +1 -1
- package/src/php/Challenge/ChallengeUtils.php +1 -1
- package/src/php/FingerprintEngine.php +1880 -1879
- package/src/php/ProblemManager.php +83 -0
- package/src/php/Utils/RequestUtils.php +9 -1
|
@@ -303,6 +303,89 @@ class ProblemManager
|
|
|
303
303
|
return false;
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
+
/**
|
|
307
|
+
* S'assure qu'un problème a une solution initiale. Si non, en génère une.
|
|
308
|
+
*
|
|
309
|
+
* @param array &$problem Le problème à vérifier (passé par référence).
|
|
310
|
+
*/
|
|
311
|
+
private function ensureInitialSolution(array &$problem): void
|
|
312
|
+
{
|
|
313
|
+
if (!empty($problem['state']['bestSolution'])) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
$scoreFunction = $problem['workUnit']['scoreFunction'] ?? null;
|
|
318
|
+
$initialSolutionSourceKey = $problem['workUnit']['initialSolutionSource'] ?? '';
|
|
319
|
+
$initialSolution = $problem['payload'][$initialSolutionSourceKey] ?? null;
|
|
320
|
+
|
|
321
|
+
if ($scoreFunction && is_array($initialSolution)) {
|
|
322
|
+
$score = $scoreFunction($initialSolution, $problem['payload'] ?? []);
|
|
323
|
+
$problem['state']['bestSolution'] = $initialSolution;
|
|
324
|
+
$problem['state']['bestEnergy'] = $score;
|
|
325
|
+
$problem['state']['lastUpdate'] = (new \DateTime())->format(\DateTime::ATOM);
|
|
326
|
+
$this->store->set("problem-state:{$problem['id']}", $problem['state']);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Formate l'état d'un problème pour l'export externe.
|
|
332
|
+
*/
|
|
333
|
+
private function formatSolution(array $problem): ?array
|
|
334
|
+
{
|
|
335
|
+
if (!isset($problem['state'])) {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (($problem['workUnit']['type'] ?? '') === 'multi_objective_genetic_algorithm') {
|
|
340
|
+
return [
|
|
341
|
+
'id' => $problem['id'],
|
|
342
|
+
'solution' => $problem['state']['paretoFront'] ?? [],
|
|
343
|
+
'score' => count($problem['state']['paretoFront'] ?? []),
|
|
344
|
+
'lastUpdate' => $problem['state']['lastUpdate'] ?? null,
|
|
345
|
+
];
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return [
|
|
349
|
+
'id' => $problem['id'],
|
|
350
|
+
'solution' => $problem['state']['bestSolution'] ?? null,
|
|
351
|
+
'score' => $problem['state']['bestEnergy'] ?? null,
|
|
352
|
+
'lastUpdate' => $problem['state']['lastUpdate'] ?? null,
|
|
353
|
+
];
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Récupère la meilleure solution actuellement connue pour un ou plusieurs problèmes.
|
|
358
|
+
*
|
|
359
|
+
* @param string|null $problemId L'ID optionnel du problème à consulter.
|
|
360
|
+
* @return array|null Un tableau associatif ou une liste de tableaux associatifs.
|
|
361
|
+
*/
|
|
362
|
+
public function getBestSolutions(?string $problemId = null): ?array
|
|
363
|
+
{
|
|
364
|
+
$problemsToProcess = [];
|
|
365
|
+
foreach ($this->problems as &$p) {
|
|
366
|
+
if ($problemId === null || $p['id'] === $problemId) {
|
|
367
|
+
if (($p['workUnit']['type'] ?? '') !== 'multi_objective_genetic_algorithm') {
|
|
368
|
+
$this->ensureInitialSolution($p);
|
|
369
|
+
}
|
|
370
|
+
$problemsToProcess[] = $p;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
unset($p);
|
|
374
|
+
|
|
375
|
+
if ($problemId !== null) {
|
|
376
|
+
return !empty($problemsToProcess) ? $this->formatSolution($problemsToProcess[0]) : null;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
$results = [];
|
|
380
|
+
foreach ($this->problems as $p) {
|
|
381
|
+
$formatted = $this->formatSolution($p);
|
|
382
|
+
if ($formatted && $formatted['solution'] !== null) {
|
|
383
|
+
$results[] = $formatted;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return $results;
|
|
387
|
+
}
|
|
388
|
+
|
|
306
389
|
/**
|
|
307
390
|
* Réinitialise l'instance singleton.
|
|
308
391
|
* @internal Uniquement pour les tests.
|
|
@@ -1358,12 +1358,20 @@ class RequestUtils
|
|
|
1358
1358
|
$suspicionDensity = $highScoreCount / $deviceCount;
|
|
1359
1359
|
$ipDeviceRatio = $ipCount / $deviceCount;
|
|
1360
1360
|
|
|
1361
|
+
// Ratio User-Agent / Device : détecte la rotation/spoofing de navigateurs sur une même empreinte matérielle
|
|
1362
|
+
$uaDeviceRatio = (double)max(1, $uaCount) / $deviceCount;
|
|
1363
|
+
$uaMultiplier = 0.6 + (0.4 * min(2.5, $uaDeviceRatio));
|
|
1364
|
+
|
|
1361
1365
|
$baseScore = 100.0 * (1.0 - exp(-0.15 * $highScoreCount));
|
|
1362
1366
|
|
|
1363
1367
|
$densityMultiplier = 0.4 + (1.6 * $suspicionDensity);
|
|
1364
1368
|
$distributionMultiplier = 0.5 + (1.0 * $ipDeviceRatio);
|
|
1365
1369
|
|
|
1366
|
-
$
|
|
1370
|
+
$dampening = 1.0;
|
|
1371
|
+
if( $highScoreCount < 3 ){
|
|
1372
|
+
$dampening = $highScoreCount / 3.0;
|
|
1373
|
+
}
|
|
1374
|
+
$finalScore = min(100.0, round($baseScore * $densityMultiplier * $distributionMultiplier * $uaMultiplier * $dampening * 10.0) / 10.0);
|
|
1367
1375
|
|
|
1368
1376
|
return ['subnetScore' => $finalScore];
|
|
1369
1377
|
}
|