@anonympins/fingerprint 0.3.1 → 0.3.3

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 (51) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/README.md +298 -37
  3. package/composer.json +38 -0
  4. package/index.js +5 -0
  5. package/package.json +100 -94
  6. package/phpunit.xml +20 -0
  7. package/public/fp.js +2 -0
  8. package/public/fp.wasm +0 -0
  9. package/src/js/build-client.js +69 -0
  10. package/{fingerprint.builder.js → src/js/fingerprint.builder.js} +168 -171
  11. package/{fingerprint.client.js → src/js/fingerprint.client.js} +634 -483
  12. package/src/js/fingerprint.client.obfuscated.js +1 -0
  13. package/{fingerprint.js → src/js/fingerprint.js} +338 -120
  14. package/{library.js → src/js/library.js} +1729 -1727
  15. package/{problem-manager.js → src/js/problem-manager.js} +539 -522
  16. package/src/php/AutoTuner.php +155 -0
  17. package/src/php/Challenge/ChallengeUtils.php +306 -0
  18. package/src/php/Config/SecurityProfiles.php +257 -0
  19. package/src/php/DirectFingerprint.php +81 -0
  20. package/src/php/FingerprintBuilder.php +185 -0
  21. package/src/php/FingerprintClient.php +118 -0
  22. package/src/php/FingerprintEngine.php +850 -0
  23. package/src/php/Optimization/FunctionRegistry.php +63 -0
  24. package/src/php/Optimization/Optimization.php +256 -0
  25. package/src/php/Optimization/OptimizationOperators.php +305 -0
  26. package/src/php/Optimization/ProblemInitializers.php +53 -0
  27. package/src/php/ProblemManager.php +255 -0
  28. package/src/php/RequestContext.php +87 -0
  29. package/src/php/Store/IStore.php +42 -0
  30. package/src/php/Store/InMemoryStore.php +67 -0
  31. package/src/php/Store/StoreManager.php +26 -0
  32. package/src/php/Tests/ChallengeUtilsTest.php +82 -0
  33. package/src/php/Tests/FingerprintBuilderTest.php +58 -0
  34. package/src/php/Tests/FingerprintEngineTest.php +219 -0
  35. package/src/php/Tests/PowTest.php +40 -0
  36. package/src/php/Tests/ProblemManagerTest.php +295 -0
  37. package/src/php/Tests/RequestUtilsTest.php +81 -0
  38. package/src/php/Tests/problems.config.json +9 -0
  39. package/src/php/Utils/BigInt.php +102 -0
  40. package/src/php/Utils/BlockList.php +100 -0
  41. package/src/php/Utils/Logger.php +30 -0
  42. package/src/php/Utils/MaliciousPatterns.php +59 -0
  43. package/src/php/Utils/RequestUtils.php +673 -0
  44. package/fingerprint.client.obfuscated.js +0 -1
  45. /package/{mongodb-store.js → src/js/mongodb-store.js} +0 -0
  46. /package/{optimization.worker.js → src/js/optimization.worker.js} +0 -0
  47. /package/{pow.solver.inline.js → src/js/pow.solver.inline.js} +0 -0
  48. /package/{pow.solver.js → src/js/pow.solver.js} +0 -0
  49. /package/{pow.worker.js → src/js/pow.worker.js} +0 -0
  50. /package/{redis-store.js → src/js/redis-store.js} +0 -0
  51. /package/{sql-store.js → src/js/sql-store.js} +0 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,172 @@
1
+ ## Version 0.3.3
2
+
3
+ This release introduces significant enhancements to client-side behavioral analysis, adds a crucial "dry run" mode for safe production testing, and improves the overall developer experience with an event-driven client library and better packaging.
4
+
5
+ ### ✨ New Features
6
+
7
+ * **Advanced Behavioral Analysis: Click Variance**:
8
+ * The client-side library now tracks the exact coordinates of user clicks on interactive elements.
9
+ * A new `clickVarianceScore` is calculated on the server-side (for both PHP and Node.js) to penalize unnaturally precise, bot-like clicking patterns (e.g., always hitting the exact same pixel). This adds a powerful new dimension to detecting sophisticated automation.
10
+
11
+ * **"Dry Run" Mode**:
12
+ * A `dryRun: true` option can now be added to the security configuration. When enabled, the engine performs all calculations and logs the action it *would* have taken (`block`, `challenge`) but never actually interrupts the request.
13
+ * This is invaluable for safely testing new or stricter configurations in a live production environment without affecting real users.
14
+
15
+ * **Client-Side Event Emitter**:
16
+ * The client library now emits events for key actions (e.g., `challenge_issued`, `challenge_solved`, `honeypot_triggered`). This allows developers to easily hook into the library's lifecycle to trigger custom UI changes, analytics, or logging.
17
+
18
+ ### 🚀 Improvements
19
+
20
+ * **Enhanced Mouse Tracking Analysis**: The server-side analysis of mouse movement data has been refined to better distinguish between natural, human-like cursor paths and the linear or predictable movements typical of bots.
21
+ * **PHP Code Quality**: The entire PHP codebase has undergone a syntax normalization pass, improving consistency and long-term maintainability.
22
+ * **Test Suite Reliability**:
23
+ * Unit tests for the client-side `initializeClient` function have been added and improved.
24
+ * New unit tests cover the "Dry Run" mode functionality.
25
+ * Fixed existing unit tests for the `ProblemManager` to ensure the stability of the Useful-Proof-of-Work system.
26
+
27
+ ### 📦 Build & Internals
28
+
29
+ * **Corrected NPM Package Files**: The `files` array in `package.json` has been updated to ensure all necessary JavaScript source files (`library.js`, `fingerprint.builder.js`, etc.) are correctly included in the published package, fixing potential `import` issues for users.
30
+ * **Project Structure**: The JavaScript source files have been consolidated into the `src/js` directory for a cleaner and more organized project structure.
31
+
32
+ ## Version 0.3.2
33
+
34
+ This release brings major new capabilities to both the Node.js and PHP versions of the library. Key highlights include the full implementation of the "Useful Proof-of-Work" (uPoW) system in PHP, client-side acceleration via WebAssembly (WASM), direct JA3 fingerprinting in Node.js, and significant reliability improvements to the auto-tuner.
35
+
36
+ ### ✨ New Features
37
+
38
+ * **Useful Proof-of-Work (uPoW) in PHP**: The PHP version now has full feature parity with Node.js for uPoW.
39
+ * The `ProblemManager` is now fully implemented in PHP, allowing it to load, manage, and dispatch complex optimization problems (e.g., TSP, Portfolio Allocation) to suspicious clients.
40
+ * Client solutions are integrated back into the system, enabling distributed, collaborative problem-solving.
41
+
42
+ * **WASM-Accelerated Client**: The client-side library can now be accelerated with a WebAssembly module for high-performance hashing.
43
+ * The build process (`build-client.js`) now includes a step to compile the C++ hashing utility into a WASM module.
44
+ * The client library (`fingerprint.client.js`) can dynamically load the WASM module if available, falling back gracefully to the pure JavaScript implementation. This makes client-side fingerprinting faster and harder to tamper with.
45
+
46
+ * **Direct JA3 Fingerprinting in Node.js**: The Node.js engine can now calculate the JA3 fingerprint directly from the raw TLS `clientHello` object. This is a major enhancement, as it removes the hard dependency on a reverse proxy (like Nginx or Cloudflare) to provide the JA3 hash, making the library more versatile and easier to deploy in various environments.
47
+
48
+ * **Auto-Tuner Solution API**: A new `getBestTuningSolution()` function has been added to the Node.js version. This allows developers to programmatically retrieve and inspect the optimal configuration (`weights`, `thresholds`, `patterns`) found by the auto-tuner, which is useful for auditing and "FinOps".
49
+
50
+ ### 🚀 Improvements
51
+
52
+ * **Probationary Tickets in PHP**: The PHP engine now supports issuing short-lived "probationary" tickets for moderately suspicious users who solve a challenge. This forces a quicker re-evaluation, increasing security for borderline cases.
53
+ * **Auto-Tuner Reliability**: The auto-tuning mechanism has been made more robust, with fixes to default score calculations to improve its initial learning phase and overall stability.
54
+ * **PHP 64-Bit Compatibility**: The PHP implementation of the `cyrb53` hashing algorithm and other arithmetic operations has been improved using the `gmp` extension to ensure correct and consistent results on 64-bit systems, matching the JavaScript output.
55
+ * **Expanded PHP Test Coverage**: The PHPUnit test suite has been significantly expanded to cover the new `ProblemManager`, uPoW logic, and other core engine features, increasing overall reliability.
56
+
57
+ ## Version 0.3.1
58
+
59
+ This release marks a major expansion of the library, introducing a full-featured PHP version that mirrors the capabilities of the Node.js module. It also adds GraphQL operation whitelisting and an obfuscated client build for enhanced security.
60
+
61
+ ### ✨ New Features
62
+
63
+ * **Full PHP Support**: The library is now available for PHP 7.4+ with a feature set equivalent to the Node.js version.
64
+ * **Direct Integration**: A `DirectFingerprint` class allows for easy integration into any PHP application, including legacy codebases, by interacting directly with PHP's superglobals.
65
+ * **PSR-15 Middleware**: A `FingerprintMiddleware` is provided for modern, framework-agnostic integration with applications that follow PSR-7, PSR-15, and PSR-17 standards (e.g., Slim, Laminas).
66
+ * **Pluggable Datastores**: The PHP version supports the same pluggable store architecture, allowing state to be persisted in Redis, databases, or other external systems.
67
+ * **Security Profiles**: The same pre-configured security profiles (`balanced`, `strict`, `api`, etc.) are available in PHP via `SecurityProfiles::createSecurityProfile()`.
68
+ * **Client-Side Helper**: A `FingerprintClient` class is included to simplify the injection of the client-side JavaScript library and honeypot fields into PHP-rendered HTML pages.
69
+
70
+ * **GraphQL Whitelisting**: You can now whitelist specific GraphQL operations to bypass security checks. This is ideal for allowing public queries (like `GetPublicPosts`) while protecting sensitive mutations. This is supported in both Node.js and PHP.
71
+ * Example rule: `{ type: 'graphql_operation_allowlist', entries: ['query:GetPublicPosts', 'mutation:*'] }`
72
+
73
+ ### 🚀 Improvements
74
+
75
+ * **Obfuscated Client Script**: The build process now generates an obfuscated version of the client-side JavaScript library (`fingerprint.client.obfuscated.js`). This makes it significantly more difficult for attackers to reverse-engineer the client-side fingerprinting and behavioral analysis logic.
76
+ * **Expanded PHP Test Coverage**: The new PHP module includes a comprehensive suite of PHPUnit tests, ensuring the reliability and correctness of the `FingerprintEngine`, challenge verification, and scoring logic.
77
+ * **Unified Documentation**: The `README.md` has been updated with dedicated sections and quick-start guides for both Node.js and the new PHP integrations, providing clear instructions for both platforms.
78
+
79
+ ### 📦 Build & Internals
80
+
81
+ * The project structure now includes a `src/php` directory containing the full PHP library implementation.
82
+ * A `phpunit.xml` configuration has been added to manage the PHP test suite.
83
+
84
+ ## Version 0.3.0
85
+
86
+ This is a major release focused on security hardening, distributed system capabilities, and overall robustness. It introduces advanced TLS spoofing detection, protection against various resource exhaustion and data poisoning attacks, and makes the "Useful Proof-of-Work" system truly scalable.
87
+
88
+ ### 🔒 Security Enhancements
89
+
90
+ * **Advanced TLS Spoofing Detection**: The engine now performs a much deeper analysis to detect when a client is faking its identity. It cross-references the TLS JA3 fingerprint against an internal database of known browser and library signatures. A request with a `User-Agent` for Chrome but a JA3 fingerprint for a Python `requests` library will now be heavily penalized.
91
+ * **uPoW Resource Drain Protection**: Implemented a hard cap on the difficulty of "Useful Proof-of-Work" (uPoW) tasks. This prevents a malicious client from being assigned a computationally impossible task that could drain server resources during verification.
92
+ * **Memory PoW DoS Protection**: A hard cap has been added to the memory allocation size for the memory-based PoW challenge, preventing a malicious client from forcing the server to allocate excessive amounts of memory.
93
+ * **Auto-Tuner Data Poisoning Protection**: The auto-tuner is now more robust against data poisoning attacks. It better distinguishes between legitimate traffic patterns and malicious attempts to skew its learning process, ensuring the optimized parameters remain effective.
94
+ * **Invalid Nonce Protection**: The challenge-response mechanism is now hardened. Any attempt to submit a solution for an invalid or expired nonce is immediately flagged as a high-risk honeypot interaction, resulting in a block or a maximum-difficulty challenge.
95
+ * **Cryptographically Secure Randomness**: The internal library now uses `crypto.randomBytes` instead of `Math.random` for all security-sensitive operations, ensuring higher quality randomness for tasks like genetic algorithm mutations and selection.
96
+
97
+ ### ✨ New Features
98
+
99
+ * **Distributed uPoW State**: The state of "Useful Proof-of-Work" problems (e.g., the best solution found for a TSP problem) is now persisted through the configured datastore (e.g., Redis, MongoDB). This allows a cluster of server instances to collaborate on solving the same complex problems, making the system truly distributed and more powerful.
100
+
101
+ ### 🚀 Improvements
102
+
103
+ * **Smarter Fingerprint Comparison**: The `FingerprintBuilder.compare()` method is now more precise. It applies a penalty for unknown or missing keys in a fingerprint, making it better at detecting subtle differences between a legitimate user and an attacker attempting to mimic a fingerprint.
104
+ * **Configuration Validation**: The engine now checks for unknown keys in the `securityConfig` object upon initialization and will log a warning. This helps developers quickly identify typos or misconfigurations.
105
+ * **Asynchronous Problem Loading**: The `problems.config.json` file is now read asynchronously and debounced at startup, improving application start time and preventing race conditions.
106
+ * **Optional Peer Dependencies**: The `package.json` has been updated to mark datastore drivers (`ioredis`, `mongodb`, `knex`, `sqlite3`) as optional `peerDependencies`. This provides a cleaner installation for users who do not need a specific external store.
107
+
108
+ ## Version 0.2.3
109
+
110
+ This release introduces major improvements in ease of use and flexibility. It adds pre-configured security profiles for rapid setup, more granular whitelisting controls, and expands the "Useful Proof-of-Work" system with a new range of complex optimization problems.
111
+
112
+ ### ✨ New Features
113
+
114
+ * **Security Profiles & Quick Init**:
115
+ * To simplify setup, you can now use the `createSecurityProfile()` helper to load pre-configured profiles tailored for common use cases: `balanced` (default), `strict`, `api`, `blog`, and `ecommerce`.
116
+ * These profiles provide a solid starting point and can be easily customized with your own overrides.
117
+
118
+ * **Advanced Whitelisting Controls**:
119
+ * **`path_allowlist`**: A new whitelisting rule to bypass checks for specific URL paths. It's perfect for public API endpoints, webhooks, or static content that doesn't require protection. Supports wildcards (e.g., `/api/public/*`).
120
+ * **`host_path_allowlist`**: Provides even more granular control by whitelisting a path only when it's on a specific host. This is ideal for multi-tenant applications or for securing an API on one domain but not another (e.g., `api.example.com/v1/webhooks/*`).
121
+
122
+ * **Expanded Useful Proof-of-Work (uPoW) Problems**:
123
+ * The `ProblemManager` is now more powerful, with support for a wider range of real-world optimization tasks that can be offloaded to suspicious clients.
124
+ * The `problems.config.json` has been updated with new examples, including:
125
+ * **Fraud Detection Tuning**: Finding optimal thresholds for fraud detection systems.
126
+ * **Facility Location**: Solving complex logistical placement problems.
127
+ * **Security Auto-Tuning**: Using client CPU to dynamically optimize the library's own security parameters.
128
+ * **CPC Optimization**: Finding optimal Cost-Per-Click values in a simulated ad-tech environment.
129
+ * The `FunctionRegistry` in `problem-manager.js` has been updated to support these new problem types.
130
+
131
+ ### 🚀 Improvements
132
+
133
+ * **Documentation**: The `README.md` has been updated to reflect the new security profiles and whitelisting options, with clear examples for each.
134
+
135
+
136
+ ## Version 0.2.2
137
+
138
+ This version marks a significant evolution from simple Proof-of-Work (PoW) to "Useful Proof-of-Work" (uPoW). Instead of solving arbitrary computational puzzles, clients now contribute to solving complex optimization problems, making the work done to verify a client's legitimacy valuable.
139
+
140
+ ### ✨ New Features
141
+
142
+ * **Useful Proof-of-Work (uPoW) System**:
143
+ * Introduced the `ProblemManager` to oversee long-running optimization problems (e.g., Traveling Salesperson Problem, Portfolio Optimization).
144
+ * Clients' PoW challenges now consist of running optimization algorithms (like Simulated Annealing or Genetic Algorithms) for a specific number of iterations/generations.
145
+ * Solutions submitted by clients are integrated back into the system, continuously improving the best-known solution for each problem over time.
146
+
147
+ * **Dynamic Problem Configuration**:
148
+ * The `problems.config.json` file now supports dynamic data generation. You can specify functions like `generate:randomPoints` or `generate:randomAssets` to create new problem instances on startup without manual data entry.
149
+
150
+ * **Best Solution API**:
151
+ * A new method, `fingerprint.getBestSolutions(problemId?)`, has been added. This allows you to retrieve the best solution found so far for a specific problem or for all active problems. This makes the results of the uPoW system accessible and useful.
152
+
153
+ * **Re-challenge for High-Suspicion Clients**:
154
+ * Clients with a very high `suspicionFactor` are now automatically issued a second challenge upon successful completion of the first. This significantly increases the cost of verification for highly suspicious actors without affecting legitimate users.
155
+
156
+
157
+ ### 🚀 Improvements
158
+
159
+ * **Smarter Challenge Difficulty**:
160
+ * The difficulty of optimization challenges now scales more intelligently with the client's `suspicionFactor`.
161
+ * A minimum difficulty has been established for challenges to ensure they are always meaningful, preventing trivial PoW tasks even for low-suspicion clients.
162
+ * Added a linear "decay" mode as an alternative to exponential scaling. If a `scalingFactor` is not defined for a problem, the difficulty increases linearly, providing a gentler curve for low-suspicion clients.
163
+
164
+ * **Data Point Capping**:
165
+ * Added a `maxDataPoints` option to problem configurations to prevent datasets (e.g., TSP points) from growing indefinitely. This ensures stable performance and memory usage over time. (Thanks, @anonympins!)
166
+ * **Enhanced Test Suite**:
167
+ * Added comprehensive unit tests for the new `ProblemManager`, ensuring the reliability of problem loading, work dispatching, solution integration, and the new dynamic configuration features.
168
+
169
+ ### Internal & Developer Experience
170
+
171
+ * The core logic for managing, dispatching, and updating optimization problems is now encapsulated within `problem-manager.js`.
172
+ * The project now uses `vitest` for running tests, as configured in `package.json`.
package/README.md CHANGED
@@ -5,7 +5,14 @@
5
5
  ![GitHub commit activity](https://img.shields.io/github/commit-activity/w/anonympins/fingerprint)
6
6
  [![Watchers](https://img.shields.io/github/watchers/anonympins/fingerprint)](https://github.com/anonympins/fingerprint/watchers)
7
7
 
8
- An HTTP(S) client mitigation and anti-bot protection library for Node.js/Express, based on digital fingerprinting and dynamic Proof-of-Work (PoW) challenges.
8
+ An HTTP(S) client mitigation and anti-bot protection library for both PHP and Node.js/Express, based on digital fingerprinting and dynamic Proof-of-Work (PoW) challenges.
9
+
10
+ ## Installation and Usage
11
+
12
+ This library is available for both **Node.js** and **PHP**.
13
+
14
+ * [PHP Quickstart](#php-quickstart)
15
+ * [Node.js Quickstart](#nodejs-quickstart)
9
16
 
10
17
  ## How It Works
11
18
 
@@ -47,17 +54,9 @@ For API clients, the challenge is delivered as a `404` JSON response, and the cl
47
54
  - **Timing Attack Protection**: Uses `crypto.timingSafeEqual` for secure validation of tickets and other signatures.
48
55
  - **Bot Whitelisting**: Includes a DNS-based verification mechanism to reliably identify and whitelist legitimate crawlers like Googlebot and Bingbot, preventing them from being challenged. The results are cached for optimal performance.
49
56
  - **Automatic Parameter Tuning**: Includes a genetic algorithm-based optimizer (`startThresholdAutoTuning`) that analyzes real traffic to dynamically adjust suspicion thresholds, weights, and behavioral pattern detection parameters, improving accuracy and reducing false positives over time. The tuner is hardened against data poisoning attempts.
57
+ - **Optional WASM Acceleration**: The client-side library can be accelerated with a WebAssembly module for high-performance hashing. The build process handles this optionally, and the client gracefully falls back to a pure JavaScript implementation if WASM is unavailable.
50
58
  - **Hardened Security**: Protects against various attacks, including DoS via memory exhaustion, invalid nonce submission, and uses cryptographically secure randomness for all sensitive operations.
51
59
 
52
- ## Installation and Usage
53
-
54
- This library is available for both **Node.js** and **PHP**.
55
-
56
- * [Node.js (Express) Quickstart](#nodejs-express)
57
- * [PHP Quickstart](#php)
58
- * [PHP Quickstart (Direct Integration)](#php-quickstart-direct-integration)
59
- * [PHP Quickstart (PSR-15 Middleware)](#php-quickstart-psr-15-middleware)
60
-
61
60
  ### Prerequisites
62
61
 
63
62
  * **PHP 7.4+**
@@ -66,7 +65,7 @@ This library is available for both **Node.js** and **PHP**.
66
65
 
67
66
  ---
68
67
 
69
- ### Prerequisites
68
+ <a id="php-quickstart"></a>
70
69
 
71
70
  ## PHP Quickstart (Direct Integration)
72
71
 
@@ -114,6 +113,15 @@ $securityConfig = SecurityProfiles::createSecurityProfile('balanced', [
114
113
  'verbose' => true,
115
114
  ]);
116
115
 
116
+ /*
117
+ * IMPORTANT: Unlike Node.js, standard PHP environments (like PHP-FPM) cannot directly access
118
+ * the raw TLS handshake to compute JA3/JA4 fingerprints.
119
+ * To enable robust TLS fingerprinting in PHP, you must use a reverse proxy (like Nginx,
120
+ * HAProxy, or a cloud load balancer) configured to extract the fingerprint and pass it
121
+ * to your application via an HTTP header (e.g., `X-JA3-Hash`). The library is already
122
+ * built to consume these headers automatically.
123
+ */
124
+
117
125
  // 2. Create an instance of the DirectFingerprint protector.
118
126
  $protector = new DirectFingerprint($securityConfig);
119
127
 
@@ -134,13 +142,244 @@ echo "<p>Your suspicion score was: " . round($score, 2) . "</p>";
134
142
  ?>
135
143
  ```
136
144
 
137
- ### [NodeJS Configuration](nodejs-express)
145
+ ### Full Configuration Example (PHP)
138
146
 
139
- #### Prerequisites for Node.js
147
+ If you prefer to define the entire configuration manually instead of using a profile, you can create a `$securityConfig` array with all the parameters. All parameters are optional, but it is highly recommended to review and adjust them for your specific needs. The engine will warn you about any unknown keys in this configuration, helping you catch typos.
148
+
149
+ ```php
150
+ <?php
151
+
152
+ use Anonympins\Fingerprint\Utils\DefaultWhitelist;
153
+
154
+ // Array to store traffic analysis data for the auto-tuner.
155
+ // In a real application, this could be a more robust logging system.
156
+ $trafficData = [];
157
+
158
+ // Configuration of weights and thresholds for calculating the suspicion score.
159
+ // These values should be adjusted based on traffic and expected user behavior.
160
+ $securityConfig = [
161
+ 'weights' => [
162
+ 'historyScore' => 0.3, // Penalizes IP rotation (proxy)
163
+ 'rotationScore' => 0.5, // Penalizes rapid fingerprint changes (user-agent, etc.)
164
+ 'headerAnomalyScore' => 0.1, // Penalizes abnormal headers (missing UA, etc.)
165
+ 'requestPatternScore' => 0.6,// Penalizes bot-like request sequences (scraping, etc.)
166
+ 'inconsistencyScore' => 0.8, // Strongly penalizes inconsistency between the current and initial fingerprint (stolen cookie)
167
+ 'behaviorScore' => 0.7, // Penalizes non-human interactions (no mouse/keyboard activity)
168
+ 'honeypotScore' => 1.0, // Strongly penalizes bots filling hidden form fields
169
+ 'crossLayerInconsistencyScore' => 0.4, // Penalizes mismatches between client-side data (e.g., OS) and server-side headers (e.g., User-Agent)
170
+ 'timeInconsistencyScore' => 0.9, // Strongly penalizes large time gaps between client metric collection and server reception (replay attack)
171
+ 'tlsSpoofingScore' => 0.8, // Penalizes mismatches between the TLS fingerprint (JA3/JA4) and the User-Agent (client spoofing)
172
+ 'botScore' => 1.0, // Penalizes explicit bot markers from the client
173
+ 'cookieDroppingScore' => 0.9, // Penalizes clients that appear to be intentionally dropping cookies
174
+ 'threatIntelScore' => 0.4, // Penalizes requests from known malicious IPs (proxies, Tor, etc.)
175
+ ],
176
+ 'thresholds' => [
177
+ 'low' => 20, // Score from which a CPU challenge is issued
178
+ 'medium' => 45, // Score for a more difficult combined CPU/Memory challenge
179
+ 'high' => 75, // Score for a very difficult challenge
180
+ 'block' => 95, // Score above which the request is blocked outright (HTTP 403)
181
+ ],
182
+ 'cpu' => [
183
+ 'minDifficultyBits' => 8,
184
+ 'maxDifficultyBits' => 24,
185
+ ],
186
+ // (Optional) Configure the duration (in milliseconds) for various temporary data.
187
+ 'ticketMaxAge' => 3600000, // 1 hour. Duration for which a solved challenge ticket is valid.
188
+ 'challengeTtl' => 300000, // 5 minutes. Time during which a challenge nonce is valid.
189
+ 'deviceIdCookieMaxAge' => null, // By default, it's a session cookie. Set a value in ms for a persistent cookie.
190
+ 'challengePagePath' => './path/to/your/custom-challenge-page.html', // (Optional) Path to a custom HTML template for the challenge page.
191
+ 'verbose' => ($_ENV['APP_ENV'] ?? 'production') !== 'production', // Log detailed info in development.
192
+ 'patterns' => [ // (Optional) Initial values for request pattern detection, optimized by auto-tuner if enabled.
193
+ 'historySize' => 10, // Number of requests to keep for pattern analysis
194
+ 'minSamples' => 5, // Minimum number of timings to collect before statistical analysis.
195
+ 'regularityThreshold' => 50, // Standard deviation (ms) below which behavior is "too regular".
196
+ 'benfordThreshold' => 0.15, // Benford's Law deviation threshold above which the distribution is "unnatural".
197
+ 'patternWeight' => 80, // Strong, one-time penalty when a pattern is detected.
198
+ 'decayFactor' => 0.9, // Factor by which the pattern score decreases over time.
199
+ 'inactivityReset' => 5000, // Time (ms) after which the pattern score is reset.
200
+ ],
201
+ 'honeypot' => [
202
+ // List of field names that are traps for bots.
203
+ 'fields' => ['email_confirm', 'user_nickname', 'debug', 'test_mode', 'admin'], // (Optional)
204
+ // List of URL paths that should never be accessed by a legitimate user.
205
+ 'trapUrls' => ['/wp-admin', '/.env', '/admin.php', '/phpmyadmin'], // (Optional)
206
+ // Automatically detect common injection patterns. Can be a boolean or an array of specific types.
207
+ 'detectInjections' => ['sql', 'rce', 'traversal', 'xxe', 'ssti', 'log4shell'], // (Optional, default: true)
208
+ // (Optional) Plug in external analyzers. Each must be a callable that receives request data
209
+ // and returns `true` if a threat is detected.
210
+ 'analyzers' => [
211
+ // Example: A custom function to detect specific keywords (e.g., for anti-spam).
212
+ function ($data) {
213
+ $spamKeywords = ['viagra', 'free money', 'crypto pump'];
214
+ $dataString = strtolower(json_encode($data));
215
+ foreach ($spamKeywords as $keyword) {
216
+ if (str_contains($dataString, $keyword)) {
217
+ return true;
218
+ }
219
+ }
220
+ return false;
221
+ }
222
+ ]
223
+ ],
224
+ // (Optional) Whitelisting configuration.
225
+ 'whitelist' => [
226
+ // Option 1: Static IP Allowlist (IPs or CIDR ranges).
227
+ [
228
+ 'type' => 'allowlist',
229
+ 'entries' => [
230
+ '192.168.1.100', // A specific internal IP
231
+ '203.0.113.0/24', // A partner's network range
232
+ '2001:db8::/32', // An IPv6 range
233
+ ]
234
+ ],
235
+ // Option 2: Host + Path Allowlist (supports wildcards).
236
+ [
237
+ 'type' => 'host_path_allowlist',
238
+ 'entries' => [
239
+ 'api.yourdomain.com/v1/webhooks/*', // All paths under /v1/webhooks on a specific host
240
+ ]
241
+ ],
242
+ // Option 3: Path Allowlist (supports wildcards).
243
+ [
244
+ 'type' => 'path_allowlist',
245
+ 'entries' => [
246
+ '/api/v2/public-stats', // Exact path
247
+ '/callbacks/trusted-source/*', // All paths under /callbacks/trusted-source/
248
+ ]
249
+ ],
250
+ // Option 4: GraphQL Operation Allowlist (supports wildcards).
251
+ [
252
+ 'type' => 'graphql_operation_allowlist',
253
+ 'entries' => [
254
+ 'query:GetPublicPosts', // A specific query
255
+ 'mutation:*' // All mutations
256
+ ]
257
+ ],
258
+ // Option 5: DNS-verified bots (e.g., search engine crawlers).
259
+ // You can use the provided default list and extend it.
260
+ ...DefaultWhitelist::getRules(), // Use the defaults
261
+ ['userAgent' => 'MyCustomBot', 'hostnameSuffix' => '.my-bot-verifier.com'], // Add a custom bot
262
+ ],
263
+ // (Optional) Custom function to identify API requests. Must be a callable.
264
+ 'isApiRequest' => function (RequestContext $context) {
265
+ return str_starts_with($context->path, '/api/') ||
266
+ str_contains($context->getHeader('accept') ?? '', 'application/json');
267
+ },
268
+ // The logger is required for auto-tuning. It must be a callable.
269
+ 'logger' => function ($log) use (&$trafficData) {
270
+ $trafficData[] = $log;
271
+ },
272
+ // (Optional) Configuration for the automatic threshold and pattern tuning.
273
+ 'autotuning' => [
274
+ 'trafficData' => &$trafficData, // Pass the data source by reference.
275
+ 'interval' => 1800, // Optimization cycle every 30 minutes (in seconds for a cron job).
276
+ 'minDataPoints' => 200,
277
+ 'maxDataPoints' => 20000,
278
+ 'savePath' => './security-config.optimized.json' // (Optional) Save the best config found.
279
+ ],
280
+ // Enables "Useful Proof-of-Work" for suspicious activity.
281
+ 'enableUsefulWork' => true,
282
+ // Provide either a path to a JSON file or the configuration as an array.
283
+ 'usefulWorkConfigPath' => './path/to/your/problems.config.json', // (Optional)
284
+ // Or provide the configuration directly as an array.
285
+ // 'usefulWorkConfig' => [ /* ... your problem definitions ... */ ]
286
+ ];
287
+
288
+ ```
289
+ ## TLS Fingerprinting (JA3/JA4) with Nginx and Apache
290
+
291
+ Unlike Node.js, which can directly inspect the TLS handshake, a standard PHP environment (such as PHP-FPM) runs behind a web server (Nginx, Apache) that terminates the TLS connection. Consequently, the PHP script lacks direct access to the low-level information required to calculate the JA3 fingerprint.
292
+
293
+ If you want a **better protection**, the standard solution is to delegate this calculation to the front-end web server (or a reverse proxy like HAProxy) and pass the result to PHP via an HTTP header. The library is designed to automatically detect and utilize these headers.
294
+
295
+ ### Automatic Detection in the Library
296
+
297
+ The PHP `RequestContext` class automatically looks for the following headers.
298
+
299
+ Once these headers are present, the `FingerprintEngine` incorporates them into the composite device fingerprint, providing the same level of robustness as the Node.js version.
300
+
301
+ ---
302
+
303
+ ### Configuration with Nginx
304
+
305
+ Nginx is the simplest and most common solution. It requires your Nginx instance to be compiled with the `ngx_http_ssl_ja3_module` module. Many modern Nginx builds or distribution-provided packages include it. Here is an example configuration:
306
+
307
+ ```nginx
308
+ http {
309
+ # ... other http configurations ...
310
+
311
+ # Declare a variable to store the JA3 fingerprint.
312
+ # Nginx automatically populates $ssl_ja3_hash if the module is active.
313
+ map $ssl_ja3_hash $ja3_hash {
314
+ default $ssl_ja3_hash;
315
+ }
316
+
317
+ server {
318
+ listen 443 ssl http2;
319
+ server_name yourdomain.com;
320
+
321
+ # ... SSL configuration (certificates, etc.) ...
322
+ ssl_certificate /path/to/your/fullchain.pem;
323
+ ssl_certificate_key /path/to/your/privkey.pem;
324
+
325
+ location / {
326
+ # ... your application configuration ...
327
+ try_files $uri $uri/ /index.php?$query_string;
328
+ }
329
+
330
+ location ~ \.php$ {
331
+ include fastcgi_params;
332
+ fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; # Adjust for your PHP version
333
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
334
+
335
+ # Add the JA3 fingerprint as a FastCGI parameter.
336
+ # PHP will make it available in $_SERVER['HTTP_X_JA3_HASH'].
337
+ fastcgi_param HTTP_X_JA3_HASH $ja3_hash;
338
+ }
339
+ }
340
+ }
341
+ ```
342
+
343
+ After reloading the Nginx configuration, the `X-JA3-Hash` header will be automatically available to your PHP application.
344
+
345
+ ---
346
+
347
+ ### Configuration with Apache
348
+
349
+ For Apache, obtaining the JA3 fingerprint is less straightforward because there is no standard module as widely available as the one for Nginx.
350
+
351
+ #### Option 1: `mod_ssl_ja3` module (Recommended)
352
+
353
+ The best approach is to use a third-party module like `mod_ssl_ja3`. You will need to compile and load it into your Apache configuration. Once the module is installed and enabled, you can add the JA3 header to your requests using the `RequestHeader` directive in your Virtual Host configuration:
354
+
355
+ ```apache
356
+ <VirtualHost *:443>
357
+ ServerName yourdomain.com
358
+ # ... SSL configuration ...
359
+
360
+ # The JA3_HASH environment variable is provided by mod_ssl_ja3
361
+ RequestHeader set X-JA3-Hash "%{JA3_HASH}e"
362
+
363
+ # ... your PHP application configuration ...
364
+ </VirtualHost>
365
+ ```
366
+
367
+ #### Option 2: Using a Reverse Proxy in front of Apache
368
+
369
+ If you cannot compile modules for Apache, a very robust alternative is to place another service in front to handle TLS termination. **HAProxy** is an excellent choice for this, as it can calculate the JA3 hash natively and add it as a header before forwarding the request (via plain HTTP) to Apache.
370
+
371
+ This architecture is common in high-performance environments and offers great flexibility.
372
+
373
+ ---
374
+
375
+ <a id="nodejs-quickstart"></a>
376
+ ## NodeJS Quickstart
377
+
378
+ ### Prerequisites for Node.js
140
379
 
141
380
  Ensure you have middleware for parsing cookies (like `cookie-parser`) and request bodies (like `express.json` and `express.urlencoded`) set up in your Express application *before* the `powMiddleware`.
142
381
 
143
- #### Configuration
382
+ ### Configuration
144
383
  Define a secret key for signing PoW tickets in your environment variables.
145
384
 
146
385
  ```bash
@@ -162,7 +401,7 @@ Available profiles:
162
401
  import express from 'express';
163
402
  import bodyParser from 'body-parser';
164
403
  import cookieParser from 'cookie-parser';
165
- import { powMiddleware, createSecurityProfile } from './fingerprint.js'; // Adjust the path
404
+ import { powMiddleware, createSecurityProfile } from '@anonympins/fingerprint'; // Adjust the path
166
405
 
167
406
  const app = express();
168
407
  app.use(cookieParser());
@@ -189,7 +428,8 @@ const securityConfig = createSecurityProfile('api', {
189
428
  trafficData: trafficData,
190
429
  interval: 1800000, // 30 minutes
191
430
  minDataPoints: 200,
192
- }
431
+ savePath: './security-config.optimized.json' // (Optional) Save the best config found.
432
+ },
193
433
  });
194
434
 
195
435
  // Create an instance of the middleware with your security configuration.
@@ -221,7 +461,7 @@ app.listen(3000, () => console.log('Server started on port 3000'));
221
461
  If you prefer to define the entire configuration manually instead of using a profile, you can create a `securityConfig` object with all the parameters. All parameters are optional, but it is highly recommended to review and adjust them for your specific needs. The engine will warn you about any unknown keys in this configuration, helping you catch typos.
222
462
 
223
463
  ```javascript
224
- import { default_whitelist, default_analyzers } from './fingerprint.js';
464
+ import { powMiddleware, default_whitelist, default_analyzers } from '@anonympins/fingerprint';
225
465
 
226
466
  const app = express();
227
467
  app.use(cookieParser());
@@ -255,7 +495,7 @@ const securityConfig = {
255
495
  },
256
496
  cpu: {
257
497
  minDifficultyBits: 8,
258
- maxDifficultyBits: 24,
498
+ maxDifficultyBits: 32,
259
499
  },
260
500
  // (Optional) Configure the duration (in milliseconds) for various temporary data.
261
501
  ticketMaxAge: 3600000, // 1 hour. Duration for which a solved challenge ticket is valid.
@@ -313,7 +553,8 @@ const securityConfig = {
313
553
  { type: 'allowlist', entries: [
314
554
  '192.168.1.100', // A specific internal IP
315
555
  '203.0.113.0/24', // A partner's network range
316
- '2001:db8::/32' // An IPv6 range
556
+ '2001:db8::/32', // An IPv6 range
557
+ '2a01:e0a:129:57c0::1' // A specific IPv6 address
317
558
  ]},
318
559
  { type: 'hostname_allowlist', entries: [
319
560
  'google.com', // A specific hostname
@@ -355,12 +596,22 @@ const securityConfig = {
355
596
  trafficData: trafficData, // The data source for the genetic algorithm.
356
597
  interval: 1800000, // Optimization cycle every 30 minutes (in ms).
357
598
  minDataPoints: 200, // Minimum requests before starting an optimization cycle.
358
- maxDataPoints: 20000 // Minimum requests before starting an optimization cycle.
599
+ maxDataPoints: 20000, // Maximum log entries to keep in memory.
600
+ savePath: './security-config.optimized.json' // (Optional) Save the best config found.
359
601
  },
360
602
  // Enables problem solving for suspicious activity (configurable in problems.config.json)
361
603
  enableUsefulWork: true,
362
- usefulWorkConfigPath: './path/to/your/problems.config.json' // (Optional) Path to the useful work configuration.
604
+ // (Optional) Path to the useful work configuration.
605
+ usefulWorkConfigPath: './path/to/your/problems.config.json',
606
+ // or usefulWorkConfig: [ /* ... your problem definitions ... */ ],
607
+ // (Optional) Enable "dry run" mode. The engine will calculate scores and log intended actions
608
+ // but will never actually block or challenge a request. Useful for testing new configs in production.
609
+ dryRun: false,
363
610
  };
611
+
612
+
613
+ // Create an instance of the middleware with your security configuration.
614
+ const powMiddlewareInstance = powMiddleware(securityConfig);
364
615
  ```
365
616
 
366
617
 
@@ -368,32 +619,28 @@ const securityConfig = {
368
619
 
369
620
  ## Advanced Behavioral Analysis
370
621
 
371
- The FingerprintEngine includes sophisticated behavioral analysis to detect non-human patterns. This analysis is performed by the `getRequestPatternScore` function, which is a stateful check that looks for repetitive or unnaturally fast requests from a single device.
622
+ The `FingerprintEngine` includes sophisticated behavioral analysis to detect non-human patterns. This analysis is performed by the `getRequestPatternScore` function, which is a stateful check that looks for repetitive or unnaturally fast requests from a single device.
372
623
 
373
624
  This function uses several configurable parameters to identify suspicious behavior:
374
625
 
375
- ### Core Pattern Detection
626
+ ### Statistical Analysis (Regularity and Benford's Law)
376
627
 
377
- These parameters form the basis of the request pattern analysis:
628
+ To counter more advanced bots that might try to randomize their request timings, the engine employs statistical analysis.
378
629
 
379
- * `velocityThreshold`: (Default: 800ms) Penalizes requests that are too fast to be humanly possible. If the time since the last request from a device is less than this value, the suspicion score increases.
380
- * `burstThreshold`: (Default: 1500ms) Adds a significant penalty for multiple identical requests (same path and query parameters) occurring in a very short time frame. This is a strong indicator of automated retries or brute-force attacks.
381
- * `scrapeThreshold`: (Default: 1000ms) Penalizes sequential requests to the same path but with different query parameters. This pattern is typical of scraping bots that iterate through pages or product IDs.
382
- * `sequenceLength`: (Default: 3) Detects repetitive sequences of requests (e.g., A -> B -> C -> A -> B -> C), which is a common pattern for scripted bots navigating a site.
630
+ * **Regularity Detection**: The system also calculates the standard deviation of the time intervals between requests. A very low standard deviation indicates an unnaturally regular, "cron-like" behavior, which is a strong signal of automation.
631
+ * **Benford's Law Analysis**: Benford's Law states that in many naturally occurring sets of numbers, the leading digit is more likely to be small. The timings between a human's requests tend to follow this natural distribution, whereas a bot's randomized delays often do not. The engine penalizes distributions that violate this law.
383
632
 
384
- ### Statistical Analysis (Benford's Law)
633
+ ### Core Pattern Detection Parameters
385
634
 
386
- To counter more advanced bots that might try to randomize their request timings, the engine employs statistical analysis based on Benford's Law.
635
+ These parameters form the basis of the statistical request pattern analysis:
387
636
 
388
- * **How it works**: Benford's Law states that in many naturally occurring sets of numbers, the leading digit is more likely to be small. For example, the number 1 appears as the leading digit about 30% of the time, while 9 appears less than 5% of the time. The timings between a human's requests tend to follow this natural distribution, whereas a bot's randomized delays often do not.
637
+ * `regularityThreshold`: (Default: 50ms) The standard deviation in milliseconds below which the request timing is considered "too regular" and robotic.
638
+ * `benfordThreshold`: (Default: 0.15) The deviation score from Benford's Law above which the timing distribution is considered "unnatural".
639
+ * `patternWeight`: (Default: 80) A strong, one-time penalty applied to the suspicion score if either a regularity or Benford's Law anomaly is detected.
389
640
 
390
641
  * `benfordMinSamples`: (Default: 15) The minimum number of request timings to collect before performing a Benford's Law test.
391
642
  * `benfordWeight`: (Default: 50) The weight applied to the suspicion score if the distribution of timings significantly deviates from Benford's Law.
392
643
 
393
- ### Configuration and Auto-Tuning
394
-
395
- All these parameters are part of the `patterns` object within the main security configuration and can be fine-tuned.
396
-
397
644
  ## Customizing the Challenge Page
398
645
 
399
646
  You can provide your own HTML template for the Proof-of-Work challenge page to maintain a consistent user experience with your brand.
@@ -454,7 +701,7 @@ The library provides ready-to-use adapters for popular datastores like **Redis**
454
701
  **Redis Example:**
455
702
 
456
703
  ```javascript
457
- import { configureStore } from './fingerprint.js';
704
+ import { configureStore } from '@anonympins/fingerprint';
458
705
  import { createRedisStore } from './redis-store.js';
459
706
  import Redis from 'ioredis';
460
707
 
@@ -617,6 +864,15 @@ initializeClient({
617
864
 
618
865
  // (Optional) An array of `name` attributes for hidden form fields that act as bot traps.
619
866
  honeypots: ['email_confirm', 'user_nickname', 'website_url'],
867
+
868
+ // (Optional) An array of signed trap URLs provided by the server. The client will
869
+ // dynamically inject these into the DOM to trap bots that parse the live DOM.
870
+ trapUrls: ['/backups/db.sql.gz?sig=...', '/.env?sig=...'],
871
+
872
+ // (Optional) Path to the WebAssembly loader script (`fp.js`) for accelerated hashing.
873
+ // If provided, the client will attempt to load the WASM module. If it fails or is not available,
874
+ // it will gracefully fall back to the pure JavaScript implementation.
875
+ wasmPath: '/fp.js',
620
876
 
621
877
  // (Optional) Enables automatic protection for `fetch` requests.
622
878
  // If the `fetch` object is present, the protection is active.
@@ -743,6 +999,11 @@ app.get('/api/problems/solutions', (req, res) => {
743
999
 
744
1000
  ```
745
1001
 
1002
+ #### `getBestTuningSolution()`
1003
+
1004
+ Returns the last best solution object found by the auto-tuner. This is particularly useful for "FinOps" or for auditing the tuner's performance, as it allows you to log the exact configuration that the genetic algorithm identified as optimal.
1005
+
1006
+ * **Returns**: (`object|null`) The best solution object `{ solution, objectives }` or `null` if no tuning cycle has completed yet. The `solution` property contains the optimized `weights`, `thresholds`, and `patterns`, while `objectives` contains the performance scores (e.g., false positive/negative rates) for that solution.
746
1007
 
747
1008
  #### `problemManager.updateProblemPayload(problemId, newPayload)`
748
1009
 
@@ -768,7 +1029,7 @@ Updates the payload (parameters) of a specific problem by its ID. This allows fo
768
1029
 
769
1030
  ```javascript
770
1031
  import http from 'http';
771
- import { FingerprintEngine } from './fingerprint.js'; // Adjust path
1032
+ import { FingerprintEngine } from '@anonympins/fingerprint'; // Adjust path
772
1033
 
773
1034
  const securityConfig = { /* ... your config ... */ };
774
1035
  const engine = new FingerprintEngine(securityConfig);