@anonympins/fingerprint 0.4.2 → 0.4.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/CHANGELOG.md +38 -0
- package/README.md +70 -60
- package/package.json +1 -1
- package/src/js/fingerprint.client.js +831 -635
- package/src/js/fingerprint.js +249 -31
- package/src/js/pow.solver.js +531 -497
- package/src/js/problem-manager.js +24 -0
- package/src/js/tests/fingerprint.client.init.test.js +140 -119
- package/src/js/tests/fingerprint.test.js +2451 -2319
- package/src/js/tests/pow.solver.test.js +233 -197
- package/src/js/tests/problem-manager.test.js +358 -322
- package/src/php/Challenge/ChallengeUtils.php +415 -361
- package/src/php/Config/SecurityProfiles.php +276 -271
- package/src/php/FingerprintClient.php +131 -131
- package/src/php/FingerprintEngine.php +36 -2
- package/src/php/Optimization/FunctionRegistry.php +63 -62
- package/src/php/Optimization/OptimizationOperators.php +401 -304
- package/src/php/ProblemManager.php +29 -0
- package/src/php/RequestContext.php +90 -90
- package/src/php/Store/IStore.php +41 -41
- package/src/php/Store/RedisStore.php +53 -53
- package/src/php/Tests/FingerprintEngineTest.php +330 -299
- package/src/php/Tests/ProblemManagerTest.php +376 -296
- package/src/php/Tests/RequestUtilsTest.php +386 -253
- package/src/php/Tests/problems.config.json +3 -3
- package/src/php/Utils/RequestUtils.php +201 -17
|
@@ -133,6 +133,28 @@ class ProblemManager
|
|
|
133
133
|
$task['payload'] = $task['payload'] ?? [];
|
|
134
134
|
$task['initialSolution'] = $problem['state']['bestSolution'] ?? null;
|
|
135
135
|
break;
|
|
136
|
+
|
|
137
|
+
case 'genetic_algorithm_generations':
|
|
138
|
+
$baseGenerations = max(50, $problem['workUnit']['baseGenerations'] ?? 0);
|
|
139
|
+
$task['generations'] = $scalingFactor
|
|
140
|
+
? (int)floor($baseGenerations * pow($scalingFactor, $suspicionFactor))
|
|
141
|
+
: (int)floor($baseGenerations * (0.5 + $suspicionFactor));
|
|
142
|
+
if (isset($problem['payload'])) {
|
|
143
|
+
$task['payload'] = $problem['payload'];
|
|
144
|
+
}
|
|
145
|
+
$task['payload'] = $task['payload'] ?? [];
|
|
146
|
+
$task['initialPopulation'] = $problem['state']['population'] ?? null;
|
|
147
|
+
break;
|
|
148
|
+
|
|
149
|
+
case 'run_multiple_parallel':
|
|
150
|
+
$task['solverName'] = $problem['workUnit']['solverName'] ?? null;
|
|
151
|
+
$task['numCycles'] = $problem['workUnit']['numCycles'] ?? null;
|
|
152
|
+
$task['baseSolverArgs'] = $problem['payload']['baseSolverArgs'] ?? null;
|
|
153
|
+
$task['workerDataGenerator'] = $problem['payload']['workerDataGenerator'] ?? null;
|
|
154
|
+
$task['logProgress'] = $problem['payload']['logProgress'] ?? false;
|
|
155
|
+
$task['concurrency'] = $problem['payload']['concurrency'] ?? null;
|
|
156
|
+
break;
|
|
157
|
+
|
|
136
158
|
case 'multi_objective_genetic_algorithm':
|
|
137
159
|
$baseGenerationsMulti = max(30, $problem['workUnit']['baseGenerations'] ?? 0);
|
|
138
160
|
$task['generations'] = $scalingFactor
|
|
@@ -194,6 +216,13 @@ class ProblemManager
|
|
|
194
216
|
}
|
|
195
217
|
}
|
|
196
218
|
break;
|
|
219
|
+
case 'genetic_algorithm_generations':
|
|
220
|
+
if (isset($solutionData['population']) && is_array($solutionData['population'])) {
|
|
221
|
+
$problem['state']['population'] = $solutionData['population'];
|
|
222
|
+
$problem['state']['lastUpdate'] = (new \DateTime())->format(\DateTime::ATOM);
|
|
223
|
+
$stateChanged = true;
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
197
226
|
case 'multi_objective_genetic_algorithm':
|
|
198
227
|
// Pour les algorithmes génétiques, on intègre le nouveau front de Pareto.
|
|
199
228
|
if (isset($solutionData['paretoFront']) && is_array($solutionData['paretoFront'])) {
|
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
declare(strict_types=1);
|
|
4
|
-
|
|
5
|
-
namespace Anonympins\Fingerprint;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Représente le contexte d'une requête HTTP, fournissant un accès unifié
|
|
9
|
-
* aux informations nécessaires pour l'analyse de l'empreinte.
|
|
10
|
-
* Cette classe est conçue pour être créée à partir d'un objet de requête
|
|
11
|
-
* standard (ex: PSR-7, Symfony, Laravel).
|
|
12
|
-
*/
|
|
13
|
-
class RequestContext
|
|
14
|
-
{
|
|
15
|
-
public string $clientIp;
|
|
16
|
-
public string $path;
|
|
17
|
-
/** @var array<string, string> */
|
|
18
|
-
public array $headers;
|
|
19
|
-
/** @var array<string, mixed> */
|
|
20
|
-
public array $query;
|
|
21
|
-
/** @var array<string, mixed>|object|null */
|
|
22
|
-
public $body;
|
|
23
|
-
/** @var array<string, string> */
|
|
24
|
-
public array $cookies;
|
|
25
|
-
public ?string $httpVersion;
|
|
26
|
-
public int $requestTimestamp;
|
|
27
|
-
|
|
28
|
-
/** @var ?array{type: string, name: string} */
|
|
29
|
-
public ?array $graphqlOperation = null;
|
|
30
|
-
|
|
31
|
-
/** @var ?array<string, mixed> */
|
|
32
|
-
public ?array $newCookieForResponse = null;
|
|
33
|
-
|
|
34
|
-
// Propriétés spécifiques qui peuvent être fournies par un proxy inverse
|
|
35
|
-
public ?string $ja3;
|
|
36
|
-
public ?string $ja4;
|
|
37
|
-
public ?string $ja4s;
|
|
38
|
-
public ?string $ja4h;
|
|
39
|
-
public ?string $http2Fingerprint;
|
|
40
|
-
public ?string $tcpFingerprint;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @param string $clientIp
|
|
44
|
-
* @param string $path
|
|
45
|
-
* @param array<string, string> $headers
|
|
46
|
-
* @param array<string, mixed> $query
|
|
47
|
-
* @param array<string, mixed>|object|null $body
|
|
48
|
-
* @param array<string, string> $cookies
|
|
49
|
-
* @param string|null $httpVersion
|
|
50
|
-
* @param int|null $requestTimestamp
|
|
51
|
-
*/
|
|
52
|
-
public function __construct(
|
|
53
|
-
string $clientIp,
|
|
54
|
-
string $path,
|
|
55
|
-
array $headers,
|
|
56
|
-
array $query,
|
|
57
|
-
$body,
|
|
58
|
-
array $cookies,
|
|
59
|
-
?string $httpVersion,
|
|
60
|
-
?int $requestTimestamp = null
|
|
61
|
-
) {
|
|
62
|
-
$this->clientIp = $clientIp;
|
|
63
|
-
$this->path = $path;
|
|
64
|
-
// Normaliser les en-têtes en minuscules pour un accès cohérent
|
|
65
|
-
$this->headers = array_change_key_case($headers, CASE_LOWER);
|
|
66
|
-
$this->query = $query;
|
|
67
|
-
$this->body = $body;
|
|
68
|
-
$this->cookies = $cookies;
|
|
69
|
-
$this->httpVersion = $httpVersion;
|
|
70
|
-
$this->requestTimestamp = $requestTimestamp ?? (int)(microtime(true) * 1000);
|
|
71
|
-
|
|
72
|
-
// Extraire les empreintes TLS/HTTP2/TCP si elles sont fournies par les en-têtes
|
|
73
|
-
$this->ja3 = $this->headers['x-ja3-hash'] ?? null;
|
|
74
|
-
$this->ja4 = $this->headers['x-ja4-hash'] ?? null;
|
|
75
|
-
$this->ja4s = $this->headers['x-ja4s-hash'] ?? null;
|
|
76
|
-
$this->ja4h = $this->headers['x-ja4h-hash'] ?? null;
|
|
77
|
-
$this->http2Fingerprint = $this->headers['x-http2-fingerprint'] ?? null;
|
|
78
|
-
$this->tcpFingerprint = $this->headers['x-tcp-fingerprint'] ?? null;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Récupère la valeur d'un en-tête HTTP de manière insensible à la casse.
|
|
82
|
-
*
|
|
83
|
-
* @param string $name Le nom de l'en-tête.
|
|
84
|
-
* @return string|null La valeur de l'en-tête ou null si non trouvé.
|
|
85
|
-
*/
|
|
86
|
-
|
|
87
|
-
public function getHeader(string $name): ?string
|
|
88
|
-
{
|
|
89
|
-
return $this->headers[strtolower($name)] ?? null;
|
|
90
|
-
}
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types=1);
|
|
4
|
+
|
|
5
|
+
namespace Anonympins\Fingerprint;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Représente le contexte d'une requête HTTP, fournissant un accès unifié
|
|
9
|
+
* aux informations nécessaires pour l'analyse de l'empreinte.
|
|
10
|
+
* Cette classe est conçue pour être créée à partir d'un objet de requête
|
|
11
|
+
* standard (ex: PSR-7, Symfony, Laravel).
|
|
12
|
+
*/
|
|
13
|
+
class RequestContext
|
|
14
|
+
{
|
|
15
|
+
public string $clientIp = '';
|
|
16
|
+
public string $path = '';
|
|
17
|
+
/** @var array<string, string> */
|
|
18
|
+
public array $headers = [];
|
|
19
|
+
/** @var array<string, mixed> */
|
|
20
|
+
public array $query = [];
|
|
21
|
+
/** @var array<string, mixed>|object|null */
|
|
22
|
+
public $body = null;
|
|
23
|
+
/** @var array<string, string> */
|
|
24
|
+
public array $cookies = [];
|
|
25
|
+
public ?string $httpVersion = null;
|
|
26
|
+
public int $requestTimestamp = 0;
|
|
27
|
+
|
|
28
|
+
/** @var ?array{type: string, name: string} */
|
|
29
|
+
public ?array $graphqlOperation = null;
|
|
30
|
+
|
|
31
|
+
/** @var ?array<string, mixed> */
|
|
32
|
+
public ?array $newCookieForResponse = null;
|
|
33
|
+
|
|
34
|
+
// Propriétés spécifiques qui peuvent être fournies par un proxy inverse
|
|
35
|
+
public ?string $ja3 = null;
|
|
36
|
+
public ?string $ja4 = null;
|
|
37
|
+
public ?string $ja4s = null;
|
|
38
|
+
public ?string $ja4h = null;
|
|
39
|
+
public ?string $http2Fingerprint = null;
|
|
40
|
+
public ?string $tcpFingerprint = null;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param string $clientIp
|
|
44
|
+
* @param string $path
|
|
45
|
+
* @param array<string, string> $headers
|
|
46
|
+
* @param array<string, mixed> $query
|
|
47
|
+
* @param array<string, mixed>|object|null $body
|
|
48
|
+
* @param array<string, string> $cookies
|
|
49
|
+
* @param string|null $httpVersion
|
|
50
|
+
* @param int|null $requestTimestamp
|
|
51
|
+
*/
|
|
52
|
+
public function __construct(
|
|
53
|
+
string $clientIp,
|
|
54
|
+
string $path,
|
|
55
|
+
array $headers,
|
|
56
|
+
array $query,
|
|
57
|
+
$body,
|
|
58
|
+
array $cookies,
|
|
59
|
+
?string $httpVersion,
|
|
60
|
+
?int $requestTimestamp = null
|
|
61
|
+
) {
|
|
62
|
+
$this->clientIp = $clientIp;
|
|
63
|
+
$this->path = $path;
|
|
64
|
+
// Normaliser les en-têtes en minuscules pour un accès cohérent
|
|
65
|
+
$this->headers = array_change_key_case($headers, CASE_LOWER);
|
|
66
|
+
$this->query = $query;
|
|
67
|
+
$this->body = $body;
|
|
68
|
+
$this->cookies = $cookies;
|
|
69
|
+
$this->httpVersion = $httpVersion;
|
|
70
|
+
$this->requestTimestamp = $requestTimestamp ?? (int)(microtime(true) * 1000);
|
|
71
|
+
|
|
72
|
+
// Extraire les empreintes TLS/HTTP2/TCP si elles sont fournies par les en-têtes
|
|
73
|
+
$this->ja3 = $this->headers['x-ja3-hash'] ?? null;
|
|
74
|
+
$this->ja4 = $this->headers['x-ja4-hash'] ?? null;
|
|
75
|
+
$this->ja4s = $this->headers['x-ja4s-hash'] ?? null;
|
|
76
|
+
$this->ja4h = $this->headers['x-ja4h-hash'] ?? null;
|
|
77
|
+
$this->http2Fingerprint = $this->headers['x-http2-fingerprint'] ?? null;
|
|
78
|
+
$this->tcpFingerprint = $this->headers['x-tcp-fingerprint'] ?? null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Récupère la valeur d'un en-tête HTTP de manière insensible à la casse.
|
|
82
|
+
*
|
|
83
|
+
* @param string $name Le nom de l'en-tête.
|
|
84
|
+
* @return string|null La valeur de l'en-tête ou null si non trouvé.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
public function getHeader(string $name): ?string
|
|
88
|
+
{
|
|
89
|
+
return $this->headers[strtolower($name)] ?? null;
|
|
90
|
+
}
|
|
91
91
|
}
|
package/src/php/Store/IStore.php
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
declare(strict_types=1);
|
|
4
|
-
|
|
5
|
-
namespace Anonympins\Fingerprint\Store;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Interface pour un système de stockage persistant.
|
|
9
|
-
* Utilisé pour stocker les données des appareils, les secrets des challenges, etc.
|
|
10
|
-
*/
|
|
11
|
-
interface IStore
|
|
12
|
-
{
|
|
13
|
-
/**
|
|
14
|
-
* Récupère une valeur associée à une clé.
|
|
15
|
-
* @param string $key
|
|
16
|
-
* @return mixed|null
|
|
17
|
-
*/
|
|
18
|
-
public function get(string $key);
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Stocke une valeur associée à une clé, avec une durée de vie optionnelle.
|
|
22
|
-
* @param string $key
|
|
23
|
-
* @param mixed $value
|
|
24
|
-
* @param int|null $ttl Durée de vie en secondes.
|
|
25
|
-
* @return void
|
|
26
|
-
*/
|
|
27
|
-
public function set(string $key, $value, ?int $ttl = null): void;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Vérifie si une clé existe dans le stockage.
|
|
31
|
-
* @param string $key
|
|
32
|
-
* @return bool
|
|
33
|
-
*/
|
|
34
|
-
public function has(string $key): bool;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Supprime une clé du stockage.
|
|
38
|
-
* @param string $key
|
|
39
|
-
* @return void
|
|
40
|
-
*/
|
|
41
|
-
public function delete(string $key): void;
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types=1);
|
|
4
|
+
|
|
5
|
+
namespace Anonympins\Fingerprint\Store;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Interface pour un système de stockage persistant.
|
|
9
|
+
* Utilisé pour stocker les données des appareils, les secrets des challenges, etc.
|
|
10
|
+
*/
|
|
11
|
+
interface IStore
|
|
12
|
+
{
|
|
13
|
+
/**
|
|
14
|
+
* Récupère une valeur associée à une clé.
|
|
15
|
+
* @param string $key
|
|
16
|
+
* @return mixed|null
|
|
17
|
+
*/
|
|
18
|
+
public function get(string $key);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Stocke une valeur associée à une clé, avec une durée de vie optionnelle.
|
|
22
|
+
* @param string $key
|
|
23
|
+
* @param mixed $value
|
|
24
|
+
* @param int|null $ttl Durée de vie en secondes.
|
|
25
|
+
* @return void
|
|
26
|
+
*/
|
|
27
|
+
public function set(string $key, $value, ?int $ttl = null): void;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Vérifie si une clé existe dans le stockage.
|
|
31
|
+
* @param string $key
|
|
32
|
+
* @return bool
|
|
33
|
+
*/
|
|
34
|
+
public function has(string $key): bool;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Supprime une clé du stockage.
|
|
38
|
+
* @param string $key
|
|
39
|
+
* @return void
|
|
40
|
+
*/
|
|
41
|
+
public function delete(string $key): void;
|
|
42
42
|
}
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
declare(strict_types=1);
|
|
4
|
-
|
|
5
|
-
namespace Anonympins\Fingerprint\Store;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Adaptateur de stockage Redis pour le moteur Fingerprint.
|
|
9
|
-
* Compatible avec phpredis et predis.
|
|
10
|
-
*/
|
|
11
|
-
class RedisStore implements IStore
|
|
12
|
-
{
|
|
13
|
-
/**
|
|
14
|
-
* @var mixed Une instance de \Redis ou de \Predis\Client
|
|
15
|
-
*/
|
|
16
|
-
private $redis;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @param mixed $redis Client Redis déjà configuré et connecté
|
|
20
|
-
*/
|
|
21
|
-
public function __construct($redis)
|
|
22
|
-
{
|
|
23
|
-
$this->redis = $redis;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public function get(string $key)
|
|
27
|
-
{
|
|
28
|
-
$value = $this->redis->get($key);
|
|
29
|
-
if ($value === false || $value === null) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
return json_decode($value, true);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public function set(string $key, $value, ?int $ttl = null): void
|
|
36
|
-
{
|
|
37
|
-
$stringValue = json_encode($value);
|
|
38
|
-
if ($ttl !== null && $ttl > 0) {
|
|
39
|
-
$this->redis->setex($key, $ttl, $stringValue);
|
|
40
|
-
} else {
|
|
41
|
-
$this->redis->set($key, $stringValue);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public function has(string $key): bool
|
|
46
|
-
{
|
|
47
|
-
return (bool)$this->redis->exists($key);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
public function delete(string $key): void
|
|
51
|
-
{
|
|
52
|
-
$this->redis->del($key);
|
|
53
|
-
}
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types=1);
|
|
4
|
+
|
|
5
|
+
namespace Anonympins\Fingerprint\Store;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Adaptateur de stockage Redis pour le moteur Fingerprint.
|
|
9
|
+
* Compatible avec phpredis et predis.
|
|
10
|
+
*/
|
|
11
|
+
class RedisStore implements IStore
|
|
12
|
+
{
|
|
13
|
+
/**
|
|
14
|
+
* @var mixed Une instance de \Redis ou de \Predis\Client
|
|
15
|
+
*/
|
|
16
|
+
private $redis;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param mixed $redis Client Redis déjà configuré et connecté
|
|
20
|
+
*/
|
|
21
|
+
public function __construct($redis)
|
|
22
|
+
{
|
|
23
|
+
$this->redis = $redis;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public function get(string $key)
|
|
27
|
+
{
|
|
28
|
+
$value = $this->redis->get($key);
|
|
29
|
+
if ($value === false || $value === null) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return json_decode($value, true);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public function set(string $key, $value, ?int $ttl = null): void
|
|
36
|
+
{
|
|
37
|
+
$stringValue = json_encode($value);
|
|
38
|
+
if ($ttl !== null && $ttl > 0) {
|
|
39
|
+
$this->redis->setex($key, $ttl, $stringValue);
|
|
40
|
+
} else {
|
|
41
|
+
$this->redis->set($key, $stringValue);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public function has(string $key): bool
|
|
46
|
+
{
|
|
47
|
+
return (bool)$this->redis->exists($key);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public function delete(string $key): void
|
|
51
|
+
{
|
|
52
|
+
$this->redis->del($key);
|
|
53
|
+
}
|
|
54
54
|
}
|