@anonympins/fingerprint 0.4.1 → 0.4.2
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 +17 -0
- package/package.json +1 -1
- package/src/js/fingerprint.js +4521 -4429
- package/src/js/problem-manager.js +590 -539
- package/src/php/AutoTuner.php +197 -154
- package/src/php/FingerprintEngine.php +1010 -1006
- package/src/php/ProblemManager.php +258 -254
- package/src/php/Tests/problems.config.json +8 -8
- package/src/php/Utils/RequestUtils.php +1189 -1169
package/src/php/AutoTuner.php
CHANGED
|
@@ -1,155 +1,198 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
declare(strict_types=1);
|
|
4
|
-
|
|
5
|
-
namespace Anonympins\Fingerprint;
|
|
6
|
-
|
|
7
|
-
use Anonympins\Fingerprint\Optimization\OptimizationOperators;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
private int $
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* @param array<
|
|
36
|
-
* @param array<string,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
$this->
|
|
42
|
-
$this->
|
|
43
|
-
$this->
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
$
|
|
123
|
-
$
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types=1);
|
|
4
|
+
|
|
5
|
+
namespace Anonympins\Fingerprint;
|
|
6
|
+
|
|
7
|
+
use Anonympins\Fingerprint\Optimization\OptimizationOperators;
|
|
8
|
+
use Anonympins\Fingerprint\Utils\RequestUtils;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Gère le processus d'auto-ajustement en arrière-plan pour les seuils et poids de sécurité.
|
|
12
|
+
* Conçu pour être exécuté périodiquement (par exemple, via une tâche cron).
|
|
13
|
+
*/
|
|
14
|
+
class AutoTuner
|
|
15
|
+
{
|
|
16
|
+
/**
|
|
17
|
+
* @var array<string, mixed> La configuration de sécurité en direct qui sera mutée.
|
|
18
|
+
*/
|
|
19
|
+
private array $securityConfig;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @var array<int, array<string, mixed>> Les données de trafic collectées.
|
|
23
|
+
*/
|
|
24
|
+
private array $trafficData;
|
|
25
|
+
|
|
26
|
+
private int $minDataPoints;
|
|
27
|
+
private int $maxDataPoints;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @var ?array<string, mixed> La dernière meilleure solution trouvée par l'optimiseur.
|
|
31
|
+
*/
|
|
32
|
+
private static ?array $lastBestSolution = null;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param array<string, mixed> &$securityConfig La configuration de sécurité (passée par référence).
|
|
36
|
+
* @param array<int, array<string, mixed>> &$trafficData Les données de trafic (passées par référence).
|
|
37
|
+
* @param array<string, int> $options Options pour l'auto-ajustement.
|
|
38
|
+
*/
|
|
39
|
+
public function __construct(array &$securityConfig, array &$trafficData, array $options = [])
|
|
40
|
+
{
|
|
41
|
+
$this->securityConfig = &$securityConfig;
|
|
42
|
+
$this->trafficData = &$trafficData;
|
|
43
|
+
$this->minDataPoints = $options['minDataPoints'] ?? 200;
|
|
44
|
+
$this->maxDataPoints = $options['maxDataPoints'] ?? 10000;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Exécute un cycle d'optimisation des seuils.
|
|
49
|
+
*/
|
|
50
|
+
public function runOptimizationCycle(): void
|
|
51
|
+
{
|
|
52
|
+
$sanitizedData = RequestUtils::sanitizeTrafficData($this->trafficData);
|
|
53
|
+
|
|
54
|
+
$highConfidenceLogs = count(array_filter(
|
|
55
|
+
$sanitizedData,
|
|
56
|
+
fn ($log) => in_array($log['type'] ?? '', ['challenge_solved', 'trap_triggered'])
|
|
57
|
+
));
|
|
58
|
+
$highConfidenceRatio = count($sanitizedData) > 0 ? $highConfidenceLogs / count($sanitizedData) : 0;
|
|
59
|
+
$minConfidenceRatio = 0.05; // Exiger au moins 5% de signaux forts.
|
|
60
|
+
$minHighConfidenceCount = 10; // Absolu de secours pour éviter le gel lors de floods
|
|
61
|
+
|
|
62
|
+
$hasEnoughSignal = $highConfidenceRatio >= $minConfidenceRatio || $highConfidenceLogs >= $minHighConfidenceCount;
|
|
63
|
+
|
|
64
|
+
if (count($sanitizedData) < $this->minDataPoints || !$hasEnoughSignal) {
|
|
65
|
+
if (count($sanitizedData) < $this->minDataPoints) {
|
|
66
|
+
echo sprintf("[AutoTuning] Reporté : %d/%d points de données.\n", count($sanitizedData), $this->minDataPoints);
|
|
67
|
+
} else {
|
|
68
|
+
echo sprintf("[AutoTuning] Reporté : Signaux de confiance insuffisants (Ratio: %.2f%% < %.2f%% et absolu: %d < %d).\n", $highConfidenceRatio * 100, $minConfidenceRatio * 100, $highConfidenceLogs, $minHighConfidenceCount);
|
|
69
|
+
}
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (count($this->trafficData) > $this->maxDataPoints) {
|
|
74
|
+
echo sprintf("[AutoTuning] Le journal de trafic a atteint %d entrées (max: %d). Troncation des données les plus anciennes.\n", count($this->trafficData), $this->maxDataPoints);
|
|
75
|
+
$this->trafficData = array_slice($this->trafficData, count($this->trafficData) - $this->maxDataPoints);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
echo sprintf("[AutoTuning] Démarrage du cycle d'optimisation complet avec %d points de données assainis.\n", count($sanitizedData));
|
|
79
|
+
|
|
80
|
+
$paretoFront = OptimizationOperators::solveFullSecurityTuning(['trafficData' => $sanitizedData]);
|
|
81
|
+
|
|
82
|
+
if (empty($paretoFront)) {
|
|
83
|
+
echo "[AutoTuning] L'optimisation n'a retourné aucune solution.\n";
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Règles de gardiennage (Sanity Guardrails) pour filtrer le front de Pareto
|
|
88
|
+
$isValidSecurityConfig = function (array $config): bool {
|
|
89
|
+
if (!isset($config['weights']) || !isset($config['thresholds'])) return false;
|
|
90
|
+
$w = $config['weights'];
|
|
91
|
+
$t = $config['thresholds'];
|
|
92
|
+
$activeWeightsSum = ($w['inconsistencyScore'] ?? 0) + ($w['tlsSpoofingScore'] ?? 0) + ($w['requestPatternScore'] ?? 0) + ($w['behaviorScore'] ?? 0) + ($w['botScore'] ?? 0);
|
|
93
|
+
if ($activeWeightsSum < 1.5) return false;
|
|
94
|
+
if ($t['low'] < 10 || $t['low'] > 35) return false;
|
|
95
|
+
if ($t['medium'] < $t['low'] + 5 || $t['medium'] > 70) return false;
|
|
96
|
+
if ($t['high'] < $t['medium'] + 5 || $t['high'] > 90) return false;
|
|
97
|
+
if ($t['block'] < $t['high'] + 5 || $t['block'] > 99) return false;
|
|
98
|
+
return true;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
$filteredFront = array_filter($paretoFront, fn ($p) => $isValidSecurityConfig($p['solution']));
|
|
102
|
+
if (empty($filteredFront)) {
|
|
103
|
+
echo "[AutoTuning] Attention : Toutes les solutions ont été rejetées par les règles de gardiennage. Rétablissement du front brut.\n";
|
|
104
|
+
$filteredFront = $paretoFront;
|
|
105
|
+
} else {
|
|
106
|
+
$filteredFront = array_values($filteredFront);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Stratégie de sélection : choisir la solution la plus équilibrée (la plus proche de l'origine).
|
|
110
|
+
$bestSolution = $filteredFront[0];
|
|
111
|
+
$minDistance = sqrt(pow($bestSolution['objectives'][0], 2) + pow($bestSolution['objectives'][1], 2));
|
|
112
|
+
|
|
113
|
+
for ($i = 1; $i < count($filteredFront); $i++) {
|
|
114
|
+
$distance = sqrt(pow($filteredFront[$i]['objectives'][0], 2) + pow($filteredFront[$i]['objectives'][1], 2));
|
|
115
|
+
if ($distance < $minDistance) {
|
|
116
|
+
$minDistance = $distance;
|
|
117
|
+
$bestSolution = $filteredFront[$i];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Logique d'inertie pour l'application de la configuration.
|
|
122
|
+
$newConfig = $bestSolution['solution'];
|
|
123
|
+
$trafficConfidence = min(1.5, max(0.3, $highConfidenceRatio * 4));
|
|
124
|
+
|
|
125
|
+
$applyInertialUpdate = function (&$currentConfig, $targetConfig, string $type, float $confidenceFactor = 1.0) {
|
|
126
|
+
if (empty($currentConfig) || empty($targetConfig)) return;
|
|
127
|
+
|
|
128
|
+
$baseLearningRate = 0.15;
|
|
129
|
+
$learningRate = max(0.02, min(0.40, $baseLearningRate * $confidenceFactor));
|
|
130
|
+
|
|
131
|
+
foreach ($currentConfig as $key => &$value) {
|
|
132
|
+
if (isset($targetConfig[$key]) && is_numeric($value)) {
|
|
133
|
+
$currentVal = (float)$value;
|
|
134
|
+
$targetVal = (float)$targetConfig[$key];
|
|
135
|
+
|
|
136
|
+
$updatedVal = $currentVal + ($targetVal - $currentVal) * $learningRate;
|
|
137
|
+
|
|
138
|
+
if ($type === 'weights') {
|
|
139
|
+
$updatedVal = max(0.05, min(1.8, $updatedVal));
|
|
140
|
+
} elseif ($type === 'patterns') {
|
|
141
|
+
if ($key === 'benfordThreshold') $updatedVal = max(0.05, min(0.30, $updatedVal));
|
|
142
|
+
elseif ($key === 'decayFactor') $updatedVal = max(0.70, min(0.98, $updatedVal));
|
|
143
|
+
elseif ($key === 'minSamples') $updatedVal = max(3, min(15, (int)round($updatedVal)));
|
|
144
|
+
elseif ($key === 'historySize') $updatedVal = max(5, min(30, (int)round($updatedVal)));
|
|
145
|
+
elseif (str_ends_with($key, 'Threshold')) $updatedVal = max(50, min(3000, (int)round($updatedVal)));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
$value = $updatedVal;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if ($type === 'thresholds') {
|
|
153
|
+
$low = max(10, min(35, $currentConfig['low']));
|
|
154
|
+
$medium = max($low + 8, min(65, $currentConfig['medium']));
|
|
155
|
+
$high = max($medium + 8, min(85, $currentConfig['high']));
|
|
156
|
+
$block = max($high + 8, min(98, $currentConfig['block']));
|
|
157
|
+
|
|
158
|
+
$currentConfig['low'] = (int)round($low);
|
|
159
|
+
$currentConfig['medium'] = (int)round($medium);
|
|
160
|
+
$currentConfig['high'] = (int)round($high);
|
|
161
|
+
$currentConfig['block'] = (int)round($block);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
$applyInertialUpdate($this->securityConfig['thresholds'], $newConfig['thresholds'], 'thresholds', $trafficConfidence);
|
|
166
|
+
$applyInertialUpdate($this->securityConfig['weights'], $newConfig['weights'], 'weights', $trafficConfidence);
|
|
167
|
+
$applyInertialUpdate($this->securityConfig['patterns'], $newConfig['patterns'], 'patterns', $trafficConfidence);
|
|
168
|
+
|
|
169
|
+
self::$lastBestSolution = $bestSolution;
|
|
170
|
+
|
|
171
|
+
echo "[AutoTuning] Nouvelle configuration de sécurité optimisée appliquée.\n";
|
|
172
|
+
echo "[AutoTuning] Objectifs atteints : " . json_encode([
|
|
173
|
+
'falsePositiveRate' => round($bestSolution['objectives'][0], 4),
|
|
174
|
+
'falseNegativeRate' => round($bestSolution['objectives'][1], 4)
|
|
175
|
+
]) . "\n";
|
|
176
|
+
echo "[AutoTuning] Nouveaux seuils : " . json_encode($this->securityConfig['thresholds']) . "\n";
|
|
177
|
+
echo "[AutoTuning] Nouveaux poids : " . json_encode($this->securityConfig['weights']) . "\n";
|
|
178
|
+
echo "[AutoTuning] Nouveaux patterns : " . json_encode($this->securityConfig['patterns']) . "\n";
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Retourne la dernière meilleure solution trouvée par l'auto-tuner.
|
|
183
|
+
* @return array<string, mixed>|null
|
|
184
|
+
*/
|
|
185
|
+
public static function getBestTuningSolution(): ?array
|
|
186
|
+
{
|
|
187
|
+
return self::$lastBestSolution;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Réinitialise la meilleure solution statique. Utile pour les tests.
|
|
192
|
+
* @internal
|
|
193
|
+
*/
|
|
194
|
+
public static function resetBestTuningSolution(): void
|
|
195
|
+
{
|
|
196
|
+
self::$lastBestSolution = null;
|
|
197
|
+
}
|
|
155
198
|
}
|