@anonympins/fingerprint 0.3.7 → 0.4.0

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +331 -244
  2. package/README.md +63 -1201
  3. package/composer.json +38 -38
  4. package/index.js +4 -4
  5. package/package.json +103 -103
  6. package/phpunit.xml +20 -20
  7. package/public/fp.js +1 -1
  8. package/public/fp.wasm +0 -0
  9. package/src/js/build-client.js +1 -1
  10. package/src/js/fingerprint.client.js +2 -0
  11. package/src/js/fingerprint.js +4429 -4220
  12. package/src/js/mongodb-store.js +79 -79
  13. package/src/js/pow.solver.inline.js +31 -0
  14. package/src/js/pow.solver.js +31 -0
  15. package/src/js/tests/fingerprint.builder.test.js +79 -0
  16. package/src/js/tests/fingerprint.client.init.test.js +120 -0
  17. package/src/js/tests/fingerprint.client.test.js +105 -0
  18. package/src/js/tests/fingerprint.engine.test.js +371 -0
  19. package/src/js/tests/fingerprint.isMalicious.test.js +117 -0
  20. package/src/js/tests/fingerprint.test.js +2319 -0
  21. package/src/js/tests/ip-reputation.test.js +132 -0
  22. package/src/js/tests/ja3AnomalyDetector.test.js +135 -0
  23. package/src/js/tests/library.test.js +96 -0
  24. package/src/js/tests/metrics.test.js +104 -0
  25. package/src/js/tests/pow.solver.test.js +198 -0
  26. package/src/js/tests/problem-manager.test.js +323 -0
  27. package/src/js/tests/stores.test.js +118 -0
  28. package/src/php/Challenge/ChallengeUtils.php +361 -305
  29. package/src/php/Config/SecurityProfiles.php +271 -266
  30. package/src/php/FingerprintBuilder.php +185 -185
  31. package/src/php/FingerprintClient.php +131 -131
  32. package/src/php/FingerprintEngine.php +1006 -1006
  33. package/src/php/Ja3AnomalyDetector.php +227 -227
  34. package/src/php/Optimization/FunctionRegistry.php +62 -62
  35. package/src/php/Optimization/Optimization.php +255 -255
  36. package/src/php/Optimization/OptimizationOperators.php +304 -304
  37. package/src/php/Store/InMemoryStore.php +66 -66
  38. package/src/php/Store/MongoDbStore.php +104 -104
  39. package/src/php/Store/RedisStore.php +53 -53
  40. package/src/php/Tests/ChallengeUtilsTest.php +81 -81
  41. package/src/php/Tests/FingerprintBuilderTest.php +57 -57
  42. package/src/php/Tests/FingerprintClientTest.php +71 -0
  43. package/src/php/Tests/FingerprintEngineTest.php +299 -299
  44. package/src/php/Tests/IpReputationTest.php +156 -156
  45. package/src/php/Tests/Ja3AnomalyDetectorTest.php +179 -179
  46. package/src/php/Tests/MetricsTest.php +45 -45
  47. package/src/php/Tests/PowTest.php +39 -39
  48. package/src/php/Tests/ProblemManagerTest.php +296 -296
  49. package/src/php/Tests/RequestUtilsTest.php +253 -145
  50. package/src/php/Tests/TLSClientHelloParserTest.php +118 -0
  51. package/src/php/Tests/problems.config.json +8 -8
  52. package/src/php/Utils/BigInt.php +144 -144
  53. package/src/php/Utils/Logger.php +29 -29
  54. package/src/php/Utils/MaliciousPatterns.php +58 -58
  55. package/src/php/Utils/MetricsManager.php +166 -166
  56. package/src/php/Utils/RequestUtils.php +31 -4
  57. package/src/php/Utils/TLSClientHelloParser.php +117 -0
  58. package/src/php/bin/auto-tune.php +117 -117
@@ -1,58 +1,58 @@
1
- <?php
2
-
3
- declare(strict_types=1);
4
-
5
- namespace Anonympins\Fingerprint\Tests;
6
-
7
- use Anonympins\Fingerprint\FingerprintBuilder;
8
- use PHPUnit\Framework\TestCase;
9
-
10
- class FingerprintBuilderTest extends TestCase
11
- {
12
- public function testCyrb53IsDeterministic(): void
13
- {
14
- $input = "test-string";
15
- // Note: The PHP and JS implementations of cyrb53 produce different hash strings
16
- // due to differences in large number handling, but they are internally consistent.
17
- $this->assertEquals(FingerprintBuilder::cyrb53($input), FingerprintBuilder::cyrb53($input));
18
- $this->assertNotEquals(FingerprintBuilder::cyrb53("a"), FingerprintBuilder::cyrb53("b"));
19
- }
20
-
21
- public function testBuilderHandlesNullAndEmptyValues(): void
22
- {
23
- $builder = new FingerprintBuilder();
24
- $builder->add('key1', 'value1');
25
- $builder->add('key2', null);
26
- $builder->add('key3', '');
27
-
28
- // The JS equivalent for this hash is '6263243896157005'
29
- $this->assertEquals('key1:6263243896157005', (string)$builder);
30
- }
31
-
32
- public function testToStringSortsKeysDeterministically(): void
33
- {
34
- $builder1 = new FingerprintBuilder();
35
- $builder1->add('b', '2')->add('a', '1');
36
-
37
- $builder2 = new FingerprintBuilder();
38
- $builder2->add('a', '1')->add('b', '2');
39
-
40
- $this->assertEquals((string)$builder1, (string)$builder2);
41
- }
42
-
43
- public function testCompareLogic(): void
44
- {
45
- $fp1 = (new FingerprintBuilder())->add('hw', '8_16')->add('gpu', 'nvidia')->__toString();
46
- $fp2 = (new FingerprintBuilder())->add('hw', '8_16')->add('gpu', 'nvidia')->__toString();
47
- $fp3 = (new FingerprintBuilder())->add('hw', '4_8')->add('gpu', 'amd')->__toString();
48
- $fp4 = (new FingerprintBuilder())->add('hw', '8_16')->add('os', 'win32')->__toString(); // Partial match
49
-
50
- $this->assertEquals(1.0, FingerprintBuilder::compare($fp1, $fp2), "Identical FPs should return 1.0");
51
- $this->assertEquals(0.0, FingerprintBuilder::compare($fp1, $fp3), "Completely different FPs should have a score of 0");
52
-
53
- $this->assertEqualsWithDelta(0.25, FingerprintBuilder::compare($fp1, $fp4), 0.2, "Partial match should have a specific score");
54
-
55
- $this->assertEquals(0.0, FingerprintBuilder::compare($fp1, ''), "Comparison with empty string should be 0.0");
56
- $this->assertEquals(0.0, FingerprintBuilder::compare(null, $fp2), "Comparison with null should be 0.0");
57
- }
1
+ <?php
2
+
3
+ declare(strict_types=1);
4
+
5
+ namespace Anonympins\Fingerprint\Tests;
6
+
7
+ use Anonympins\Fingerprint\FingerprintBuilder;
8
+ use PHPUnit\Framework\TestCase;
9
+
10
+ class FingerprintBuilderTest extends TestCase
11
+ {
12
+ public function testCyrb53IsDeterministic(): void
13
+ {
14
+ $input = "test-string";
15
+ // Note: The PHP and JS implementations of cyrb53 produce different hash strings
16
+ // due to differences in large number handling, but they are internally consistent.
17
+ $this->assertEquals(FingerprintBuilder::cyrb53($input), FingerprintBuilder::cyrb53($input));
18
+ $this->assertNotEquals(FingerprintBuilder::cyrb53("a"), FingerprintBuilder::cyrb53("b"));
19
+ }
20
+
21
+ public function testBuilderHandlesNullAndEmptyValues(): void
22
+ {
23
+ $builder = new FingerprintBuilder();
24
+ $builder->add('key1', 'value1');
25
+ $builder->add('key2', null);
26
+ $builder->add('key3', '');
27
+
28
+ // The JS equivalent for this hash is '6263243896157005'
29
+ $this->assertEquals('key1:6263243896157005', (string)$builder);
30
+ }
31
+
32
+ public function testToStringSortsKeysDeterministically(): void
33
+ {
34
+ $builder1 = new FingerprintBuilder();
35
+ $builder1->add('b', '2')->add('a', '1');
36
+
37
+ $builder2 = new FingerprintBuilder();
38
+ $builder2->add('a', '1')->add('b', '2');
39
+
40
+ $this->assertEquals((string)$builder1, (string)$builder2);
41
+ }
42
+
43
+ public function testCompareLogic(): void
44
+ {
45
+ $fp1 = (new FingerprintBuilder())->add('hw', '8_16')->add('gpu', 'nvidia')->__toString();
46
+ $fp2 = (new FingerprintBuilder())->add('hw', '8_16')->add('gpu', 'nvidia')->__toString();
47
+ $fp3 = (new FingerprintBuilder())->add('hw', '4_8')->add('gpu', 'amd')->__toString();
48
+ $fp4 = (new FingerprintBuilder())->add('hw', '8_16')->add('os', 'win32')->__toString(); // Partial match
49
+
50
+ $this->assertEquals(1.0, FingerprintBuilder::compare($fp1, $fp2), "Identical FPs should return 1.0");
51
+ $this->assertEquals(0.0, FingerprintBuilder::compare($fp1, $fp3), "Completely different FPs should have a score of 0");
52
+
53
+ $this->assertEqualsWithDelta(0.25, FingerprintBuilder::compare($fp1, $fp4), 0.2, "Partial match should have a specific score");
54
+
55
+ $this->assertEquals(0.0, FingerprintBuilder::compare($fp1, ''), "Comparison with empty string should be 0.0");
56
+ $this->assertEquals(0.0, FingerprintBuilder::compare(null, $fp2), "Comparison with null should be 0.0");
57
+ }
58
58
  }
@@ -0,0 +1,71 @@
1
+ <?php
2
+
3
+ declare(strict_types=1);
4
+
5
+ namespace Anonympins\Fingerprint\Tests;
6
+
7
+ use Anonympins\Fingerprint\FingerprintClient;
8
+ use PHPUnit\Framework\TestCase;
9
+
10
+ class FingerprintClientTest extends TestCase
11
+ {
12
+ public function testDefaultConfigurationIncludesWasmAndDefaultPath(): void
13
+ {
14
+ $client = new FingerprintClient('/js/fingerprint.client.js');
15
+ $scriptTag = $client->getScriptTag();
16
+
17
+ // Vérifie que le script principal est présent
18
+ $this->assertStringContainsString('src="/js/fingerprint.client.js"', $scriptTag);
19
+
20
+ // Vérifie les configurations WASM par défaut dans l'objet sérialisé pour le JS
21
+ $this->assertStringContainsString('"wasm":true', $scriptTag);
22
+ $this->assertStringContainsString('"wasmPath":"\/fp.js"', $scriptTag);
23
+ $this->assertStringContainsString('wasmScript.src = config.wasmPath;', $scriptTag);
24
+ }
25
+
26
+ public function testWasmCanBeOverriddenOrDisabled(): void
27
+ {
28
+ $client = new FingerprintClient('/js/fingerprint.client.js', [
29
+ 'wasm' => false,
30
+ 'wasmPath' => '/custom/path/to/wasm.js'
31
+ ]);
32
+ $scriptTag = $client->getScriptTag();
33
+
34
+ // Vérifie que les surcharges sont correctement prises en compte
35
+ $this->assertStringContainsString('"wasm":false', $scriptTag);
36
+ $this->assertStringContainsString('"wasmPath":"\/custom\/path\/to\/wasm.js"', $scriptTag);
37
+ }
38
+
39
+ public function testGenerateHoneypotFieldAddsFieldToConfig(): void
40
+ {
41
+ $client = new FingerprintClient('/js/fingerprint.client.js');
42
+
43
+ $honeypotFieldHtml = $client->generateHoneypotField('confirm_email_trap');
44
+
45
+ // Vérifie le code HTML du champ Honeypot
46
+ $this->assertStringContainsString('name="confirm_email_trap"', $honeypotFieldHtml);
47
+ $this->assertStringContainsString('tabindex="-1"', $honeypotFieldHtml);
48
+
49
+ // Vérifie que le champ s'enregistre dynamiquement dans la configuration JS finale
50
+ $scriptTag = $client->getScriptTag();
51
+ $this->assertStringContainsString('"honeypots":["confirm_email_trap"]', $scriptTag);
52
+ }
53
+
54
+ public function testNonceIsGeneratedAndAppliedToScripts(): void
55
+ {
56
+ $client = new FingerprintClient('/js/fingerprint.client.js');
57
+ $nonce = $client->getNonce();
58
+
59
+ // Vérifie que le nonce est généré correctement (32 caractères hexa)
60
+ $this->assertNotNull($nonce);
61
+ $this->assertEquals(32, strlen($nonce));
62
+
63
+ $scriptTag = $client->getScriptTag();
64
+
65
+ // Le nonce doit être présent sur la balise script HTML
66
+ $this->assertStringContainsString('nonce="' . $nonce . '"', $scriptTag);
67
+
68
+ // Et configuré dynamiquement lors de l'injection du script de chargement WASM
69
+ $this->assertStringContainsString('wasmScript.nonce = \'' . $nonce . '\'', $scriptTag);
70
+ }
71
+ }