@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.
- package/CHANGELOG.md +331 -244
- package/README.md +63 -1201
- package/composer.json +38 -38
- package/index.js +4 -4
- package/package.json +103 -103
- package/phpunit.xml +20 -20
- package/public/fp.js +1 -1
- package/public/fp.wasm +0 -0
- package/src/js/build-client.js +1 -1
- package/src/js/fingerprint.client.js +2 -0
- package/src/js/fingerprint.js +4429 -4220
- package/src/js/mongodb-store.js +79 -79
- package/src/js/pow.solver.inline.js +31 -0
- package/src/js/pow.solver.js +31 -0
- package/src/js/tests/fingerprint.builder.test.js +79 -0
- package/src/js/tests/fingerprint.client.init.test.js +120 -0
- package/src/js/tests/fingerprint.client.test.js +105 -0
- package/src/js/tests/fingerprint.engine.test.js +371 -0
- package/src/js/tests/fingerprint.isMalicious.test.js +117 -0
- package/src/js/tests/fingerprint.test.js +2319 -0
- package/src/js/tests/ip-reputation.test.js +132 -0
- package/src/js/tests/ja3AnomalyDetector.test.js +135 -0
- package/src/js/tests/library.test.js +96 -0
- package/src/js/tests/metrics.test.js +104 -0
- package/src/js/tests/pow.solver.test.js +198 -0
- package/src/js/tests/problem-manager.test.js +323 -0
- package/src/js/tests/stores.test.js +118 -0
- package/src/php/Challenge/ChallengeUtils.php +361 -305
- package/src/php/Config/SecurityProfiles.php +271 -266
- package/src/php/FingerprintBuilder.php +185 -185
- package/src/php/FingerprintClient.php +131 -131
- package/src/php/FingerprintEngine.php +1006 -1006
- package/src/php/Ja3AnomalyDetector.php +227 -227
- package/src/php/Optimization/FunctionRegistry.php +62 -62
- package/src/php/Optimization/Optimization.php +255 -255
- package/src/php/Optimization/OptimizationOperators.php +304 -304
- package/src/php/Store/InMemoryStore.php +66 -66
- package/src/php/Store/MongoDbStore.php +104 -104
- package/src/php/Store/RedisStore.php +53 -53
- package/src/php/Tests/ChallengeUtilsTest.php +81 -81
- package/src/php/Tests/FingerprintBuilderTest.php +57 -57
- package/src/php/Tests/FingerprintClientTest.php +71 -0
- package/src/php/Tests/FingerprintEngineTest.php +299 -299
- package/src/php/Tests/IpReputationTest.php +156 -156
- package/src/php/Tests/Ja3AnomalyDetectorTest.php +179 -179
- package/src/php/Tests/MetricsTest.php +45 -45
- package/src/php/Tests/PowTest.php +39 -39
- package/src/php/Tests/ProblemManagerTest.php +296 -296
- package/src/php/Tests/RequestUtilsTest.php +253 -145
- package/src/php/Tests/TLSClientHelloParserTest.php +118 -0
- package/src/php/Tests/problems.config.json +8 -8
- package/src/php/Utils/BigInt.php +144 -144
- package/src/php/Utils/Logger.php +29 -29
- package/src/php/Utils/MaliciousPatterns.php +58 -58
- package/src/php/Utils/MetricsManager.php +166 -166
- package/src/php/Utils/RequestUtils.php +31 -4
- package/src/php/Utils/TLSClientHelloParser.php +117 -0
- 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
|
+
}
|