@anonympins/fingerprint 0.4.0 → 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.
@@ -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
- * Gère le processus d'auto-ajustement en arrière-plan pour les seuils et poids de sécurité.
11
- * Conçu pour être exécuté périodiquement (par exemple, via une tâche cron).
12
- */
13
- class AutoTuner
14
- {
15
- /**
16
- * @var array<string, mixed> La configuration de sécurité en direct qui sera mutée.
17
- */
18
- private array $securityConfig;
19
-
20
- /**
21
- * @var array<int, array<string, mixed>> Les données de trafic collectées.
22
- */
23
- private array $trafficData;
24
-
25
- private int $minDataPoints;
26
- private int $maxDataPoints;
27
-
28
- /**
29
- * @var ?array<string, mixed> La dernière meilleure solution trouvée par l'optimiseur.
30
- */
31
- private static ?array $lastBestSolution = null;
32
-
33
- /**
34
- * @param array<string, mixed> &$securityConfig La configuration de sécurité (passée par référence).
35
- * @param array<int, array<string, mixed>> &$trafficData Les données de trafic (passées par référence).
36
- * @param array<string, int> $options Options pour l'auto-ajustement.
37
- */
38
- public function __construct(array &$securityConfig, array &$trafficData, array $options = [])
39
- {
40
- $this->securityConfig = &$securityConfig;
41
- $this->trafficData = &$trafficData;
42
- $this->minDataPoints = $options['minDataPoints'] ?? 200;
43
- $this->maxDataPoints = $options['maxDataPoints'] ?? 10000;
44
- }
45
-
46
- /**
47
- * Exécute un cycle d'optimisation des seuils.
48
- */
49
- public function runOptimizationCycle(): void
50
- {
51
- $highConfidenceLogs = count(array_filter(
52
- $this->trafficData,
53
- fn ($log) => in_array($log['type'], ['challenge_solved', 'trap_triggered'])
54
- ));
55
- $highConfidenceRatio = count($this->trafficData) > 0 ? $highConfidenceLogs / count($this->trafficData) : 0;
56
- $minConfidenceRatio = 0.05; // Exiger au moins 5% de signaux forts.
57
-
58
- if (count($this->trafficData) < $this->minDataPoints || $highConfidenceRatio < $minConfidenceRatio) {
59
- if (count($this->trafficData) < $this->minDataPoints) {
60
- echo sprintf("[AutoTuning] Reporté : %d/%d points de données.\n", count($this->trafficData), $this->minDataPoints);
61
- } else {
62
- echo sprintf("[AutoTuning] Reporté : Ratio de confiance insuffisant (%.2f%% < %.2f%%).\n", $highConfidenceRatio * 100, $minConfidenceRatio * 100);
63
- }
64
- return;
65
- }
66
-
67
- if (count($this->trafficData) > $this->maxDataPoints) {
68
- 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);
69
- $this->trafficData = array_slice($this->trafficData, count($this->trafficData) - $this->maxDataPoints);
70
- }
71
-
72
- echo sprintf("[AutoTuning] Démarrage du cycle d'optimisation avec %d points de données.\n", count($this->trafficData));
73
-
74
- $paretoFront = OptimizationOperators::solveFullSecurityTuning(['trafficData' => $this->trafficData]);
75
-
76
- if (empty($paretoFront)) {
77
- echo "[AutoTuning] L'optimisation n'a retourné aucune solution.\n";
78
- return;
79
- }
80
-
81
- // Stratégie de sélection : choisir la solution la plus équilibrée (la plus proche de l'origine).
82
- $bestSolution = $paretoFront[0];
83
- $minDistance = sqrt(pow($bestSolution['objectives'][0], 2) + pow($bestSolution['objectives'][1], 2));
84
-
85
- for ($i = 1; $i < count($paretoFront); $i++) {
86
- $distance = sqrt(pow($paretoFront[$i]['objectives'][0], 2) + pow($paretoFront[$i]['objectives'][1], 2));
87
- if ($distance < $minDistance) {
88
- $minDistance = $distance;
89
- $bestSolution = $paretoFront[$i];
90
- }
91
- }
92
-
93
- // Logique d'inertie pour l'application de la configuration.
94
- $newConfig = $bestSolution['solution'];
95
- $maxChangeVelocity = 0.15; // 15% de changement maximum par cycle.
96
-
97
- $applyInertialUpdate = function (&$currentConfig, $targetConfig) use ($maxChangeVelocity) {
98
- if (empty($currentConfig) || empty($targetConfig)) return;
99
-
100
- $totalCurrentWeight = 0;
101
- $totalTargetWeight = 0;
102
-
103
- foreach ($currentConfig as $key => $value) {
104
- if (isset($targetConfig[$key])) {
105
- $totalCurrentWeight += $value;
106
- $totalTargetWeight += $targetConfig[$key];
107
- }
108
- }
109
-
110
- if ($totalCurrentWeight === 0) return;
111
-
112
- $globalChangeRatio = ($totalTargetWeight - $totalCurrentWeight) / $totalCurrentWeight;
113
- $adjustmentFactor = max(-$maxChangeVelocity, min($maxChangeVelocity, $globalChangeRatio));
114
-
115
- foreach ($currentConfig as $key => &$value) {
116
- if (isset($targetConfig[$key])) {
117
- $value *= (1 + $adjustmentFactor);
118
- }
119
- }
120
- };
121
-
122
- $applyInertialUpdate($this->securityConfig['thresholds'], $newConfig['thresholds']);
123
- $applyInertialUpdate($this->securityConfig['weights'], $newConfig['weights']);
124
- $applyInertialUpdate($this->securityConfig['patterns'], $newConfig['patterns']);
125
-
126
- self::$lastBestSolution = $bestSolution;
127
-
128
- echo "[AutoTuning] Nouvelle configuration de sécurité optimisée appliquée.\n";
129
- echo "[AutoTuning] Objectifs atteints : " . json_encode([
130
- 'falsePositiveRate' => round($bestSolution['objectives'][0], 4),
131
- 'falseNegativeRate' => round($bestSolution['objectives'][1], 4)
132
- ]) . "\n";
133
- echo "[AutoTuning] Nouveaux seuils : " . json_encode($this->securityConfig['thresholds']) . "\n";
134
- echo "[AutoTuning] Nouveaux poids : " . json_encode($this->securityConfig['weights']) . "\n";
135
- echo "[AutoTuning] Nouveaux patterns : " . json_encode($this->securityConfig['patterns']) . "\n";
136
- }
137
-
138
- /**
139
- * Retourne la dernière meilleure solution trouvée par l'auto-tuner.
140
- * @return array<string, mixed>|null
141
- */
142
- public static function getBestTuningSolution(): ?array
143
- {
144
- return self::$lastBestSolution;
145
- }
146
-
147
- /**
148
- * Réinitialise la meilleure solution statique. Utile pour les tests.
149
- * @internal
150
- */
151
- public static function resetBestTuningSolution(): void
152
- {
153
- self::$lastBestSolution = null;
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
  }