@anonympins/fingerprint 0.6.0 โ 0.6.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.
- package/CHANGELOG.md +28 -0
- package/README.md +128 -119
- package/composer.json +2 -1
- package/package.json +1 -1
- 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.client.obfuscated.js +1 -1
- package/src/js/fingerprint.js +6802 -6411
- package/src/js/library.js +18 -11
- package/src/js/problem-manager.js +6 -2
- package/src/js/tests/cross_parity.test.js +17 -11
- package/src/js/tests/fingerprint.test.js +47 -10
- package/src/js/tests/metrics.test.js +157 -103
- package/src/php/Challenge/ChallengeUtils.php +69 -6
- package/src/php/Config/SecurityProfiles.php +3 -2
- package/src/php/FingerprintEngine.php +154 -21
- package/src/php/Optimization/OptimizationOperators.php +21 -21
- package/src/php/RequestContext.php +5 -0
- package/src/php/Tests/ChallengeUtilsTest.php +6 -4
- package/src/php/Tests/FingerprintEngineTest.php +186 -0
- package/src/php/Tests/MetricsTest.php +97 -45
- package/src/php/Tests/RequestUtilsTest.php +14 -14
- package/src/php/Tests/config/ed25519_key.json +4 -0
- package/src/php/Utils/Env.php +50 -0
- package/src/php/Utils/MetricsManager.php +209 -166
- package/src/php/Utils/RequestUtils.php +70 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## Version 0.6.3
|
|
2
|
+
|
|
3
|
+
- ๐ก๏ธ **Subnet & Botnet Scoring Upgrades**: Refined the IP Subnet reputation score to use an advanced, continuous analog calculation while handling potential `NaN` boundary edge cases. Enhanced the `botnetClusterScore` algorithm to improve grouping and detection precision of clustered threats.
|
|
4
|
+
- ๐ **Persistent Ed25519 Keypair Recovery**: Hardened persistent Ed25519 key loading, generation, and storage, resolving environment variable fallbacks across test environments.
|
|
5
|
+
- More unit tests and java coverage
|
|
6
|
+
- Java : security profiles added (+ wiki update)
|
|
7
|
+
- NodeJS/PHP : All weights in autotuner
|
|
8
|
+
|
|
9
|
+
## Version 0.6.2
|
|
10
|
+
|
|
11
|
+
- ๐ Java security fixes
|
|
12
|
+
- ๐ Updated peer thread list documentation and full options
|
|
13
|
+
- โก Added getMetric(name) in each language (with wiki documentation)
|
|
14
|
+
|
|
15
|
+
## Version 0.6.1
|
|
16
|
+
|
|
17
|
+
- **๐ Asymmetric Keys by Default**: Promoted Ed25519 asymmetric key binding to be active by default for validating stateless challenge tickets and cooperative signatures. This ensures secure, zero-trust validation chains out-of-the-box, preventing client-side decryption or tampering of authorization claims.
|
|
18
|
+
- **๐ก๏ธ Cooperative Peers Threat List Sharing**: Expanded the decentralized gossip protocol to support real-time sharing and synchronization of local threat intelligence (such as poisoned hardware signatures and banned ZKP public values `y`) directly between federated nodes (Contributed by @anonympins).
|
|
19
|
+
- **๐ Federated Peers & Decentralized Trust Validation**: Introduced federated peer networking to secure highly distributed deployments. This allows autonomous validation nodes to collaborate, share threat metrics, and establish consensus on suspicious device signatures without relying on a central bottleneck (Contributed by @anonympins).
|
|
20
|
+
- **How it works**:
|
|
21
|
+
1. **Peer Discovery & Secure Handshake**: Nodes register and establish cryptographically signed, peer-to-peer secure handshakes with adjacent trust boundaries.
|
|
22
|
+
2. **Decentralized Threat Gossip Protocol**: High-confidence threat signals, subnet reputation blocks, and poisoned hardware fingerprints are shared instantly across federated peers.
|
|
23
|
+
3. **Consensus-Driven Challenge Routing**: When a client presents a suspicious signature across different edge nodes, federated peers cross-verify the challenge state and solution history, mitigating distributed proxy-rotation attacks and replay attempts.
|
|
24
|
+
4. **Symmetric Trust Verification**: Prevents rogue peers from falsely whitelisting botnets through a multi-signature validation mechanism.
|
|
25
|
+
- **โก Low-Latency Peer Synchronization**: Optimized cross-peer synchronization with non-blocking async network event loops, reducing cross-lookup overhead to less than 12ms per transaction.
|
|
26
|
+
- **๐งน Active Peer Table Pruning**: Standardized and automated the garbage collection of offline or unresponsive federated nodes to protect local memory structures from exhaustion.
|
|
27
|
+
- **๐ Extensive Federated Configuration Documentation**: Added exhaustive guides and reference schemas for configuring the `federatedPeers` setup, setting up symmetric/asymmetric public key exchanges, and handling node validation.
|
|
28
|
+
|
|
1
29
|
## Version 0.6.0
|
|
2
30
|
|
|
3
31
|
- **๐ก๏ธ Cooperative Challenge Better Security**: Hardened cooperative Proof-of-Space and challenge routing mechanics within subnet peers, preventing rogue registrations and ensuring high-fidelity security validation on decentralized networks (Contributed by @anonympins).
|
package/README.md
CHANGED
|
@@ -1,120 +1,129 @@
|
|
|
1
|
-
# Fingerprint
|
|
2
|
-
|
|
3
|
-
NodeJS tests : [](https://github.com/anonympins/fingerprint/actions/workflows/ci-nodejs.yml) / PHP tests : [](https://github.com/anonympins/fingerprint/actions/workflows/ci-php.yml) / Python tests : [](https://github.com/anonympins/fingerprint/actions/workflows/ci-python.yml) / Java tests : [](https://github.com/anonympins/fingerprint/actions/workflows/ci-java.yml)
|
|
4
|
-
|
|
5
|
-
[](https://github.com/anonympins/fingerprint/releases)
|
|
6
|
-
[](https://github.com/anonympins/fingerprint/blob/main/LICENSE)
|
|
7
|
-
[](https://github.com/anonympins/fingerprint)
|
|
9
|
-
|
|
10
|
-
A multi-layered behavioral, cryptographic, and network analysis production-grade engine designed to identify and mitigate malicious requests (bots, scrapers, session hijacking, bot farms) in real-time. Supports **Node.js**, **Java**, **Python** and **PHP** environments.
|
|
11
|
-
|
|
12
|
-
It leverages multi-layer hardware fingerprinting, real-time behavioral analysis, passive network/TLS tracking, and adaptive/useful proof-of-work challenges to dynamically detect and mitigate scraping, scalping, account takeover (ATO), and sophisticated automated threats.
|
|
13
|
-
|
|
14
|
-
Supported officially on **Node.js (>=20.0.0)**, **PHP (>=8.0)**, Java (>=17), and **Python (>=3.8)**.
|
|
15
|
-
|
|
16
|
-

|
|
17
|
-
|
|
18
|
-
### Presentation video
|
|
19
|
-
|
|
20
|
-
[](https://www.youtube.com/watch?v=Ujeznl0JAl4)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
## ๐ Key Features
|
|
24
|
-
|
|
25
|
-
### 1. ๐งฌ Polymorphic Client-Side WASM & JS Solvers
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*
|
|
43
|
-
*
|
|
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
|
-
|
|
1
|
+
# Fingerprint Anti-Bot Protection: Secure Your Digital Assets
|
|
2
|
+
|
|
3
|
+
NodeJS tests : [](https://github.com/anonympins/fingerprint/actions/workflows/ci-nodejs.yml) / PHP tests : [](https://github.com/anonympins/fingerprint/actions/workflows/ci-php.yml) / Python tests : [](https://github.com/anonympins/fingerprint/actions/workflows/ci-python.yml) / Java tests : [](https://github.com/anonympins/fingerprint/actions/workflows/ci-java.yml)
|
|
4
|
+
|
|
5
|
+
[](https://github.com/anonympins/fingerprint/releases)
|
|
6
|
+
[](https://github.com/anonympins/fingerprint/blob/main/LICENSE)
|
|
7
|
+
[](https://img.shields.io/npm/dw/%40anonympins%2Ffingerprint)
|
|
8
|
+
[](https://github.com/anonympins/fingerprint)
|
|
9
|
+
|
|
10
|
+
A multi-layered behavioral, cryptographic, and network analysis production-grade engine designed to identify and mitigate malicious requests (bots, scrapers, session hijacking, bot farms) in real-time. Supports **Node.js**, **Java**, **Python** and **PHP** environments.
|
|
11
|
+
|
|
12
|
+
It leverages multi-layer hardware fingerprinting, real-time behavioral analysis, passive network/TLS tracking, and adaptive/useful proof-of-work challenges to dynamically detect and mitigate scraping, scalping, account takeover (ATO), and sophisticated automated threats.
|
|
13
|
+
|
|
14
|
+
Supported officially on **Node.js (>=20.0.0)**, **PHP (>=8.0)**, Java (>=17), and **Python (>=3.8)**.
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
|
|
18
|
+
### Presentation video
|
|
19
|
+
|
|
20
|
+
[](https://www.youtube.com/watch?v=Ujeznl0JAl4)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## ๐ Key Features: Stop Automated Threats and Protect Your Business
|
|
24
|
+
|
|
25
|
+
### 1. ๐งฌ Polymorphic Client-Side WASM & JS Solvers: Outsmart Bot Adaptation
|
|
26
|
+
* **Problem**: Sophisticated bots constantly adapt to your defenses, reverse-engineering client-side code to bypass protection.
|
|
27
|
+
* **Solution**: Our engine dynamically generates unique, randomized client-side code (WebAssembly and JavaScript) for each session. This makes it impossible for bots to fingerprint and consistently bypass your protection, forcing them to constantly re-adapt.
|
|
28
|
+
* **Benefit**: Stay one step ahead of bot developers. Your defenses evolve with every request, making automated attacks economically unviable.
|
|
29
|
+
|
|
30
|
+
### 2. ๐ฑ Useful Proof-of-Work (uPoW) & PoSpace: Eliminate Bot Farm Profitability
|
|
31
|
+
* **Problem**: Traditional CAPTCHAs and simple PoW puzzles are easily automated or solved by bot farms, leading to high operational costs for you and low costs for attackers.
|
|
32
|
+
* **Solution**: We force suspicious clients to solve complex, real-world optimization problems (e.g., Traveling Salesperson, Fraud Detection parameter tuning) or prove significant storage allocation. This work is valuable to you, and computationally expensive for bot farms.
|
|
33
|
+
* **Benefit**: Turn bot activity into a resource drain for attackers. By making large-scale automated attacks economically unviable, you protect your resources and ensure fair access for legitimate users.
|
|
34
|
+
|
|
35
|
+
### 3. ๐ Passive Network Signature Analysis: Unmask Stealthy Bots
|
|
36
|
+
* **Problem**: Advanced bots try to mimic real browsers, but often fail to replicate genuine network signatures, allowing them to slip past basic defenses.
|
|
37
|
+
* **Solution**: Our engine analyzes deep network layers (TLS, HTTP/2, TCP/IP stack) to identify unique digital fingerprints. This includes inspecting TLS handshake details (JA3/JA4), HTTP/2 settings, and even raw TCP packet characteristics (like TTL and Window Size) to classify the true nature of the client.
|
|
38
|
+
* **Benefit**: Detect and block bots that attempt to spoof their identity at the transport layer, revealing their true automated nature regardless of their declared User-Agent.
|
|
39
|
+
|
|
40
|
+
### 4. ๐ง Stateful Behavioral Entropy & Click Variance: Distinguish Humans from Robots
|
|
41
|
+
* **Problem**: Bots can simulate basic interactions, but they lack the subtle, natural imperfections of human behavior, making them hard to differentiate from real users.
|
|
42
|
+
* **Solution**: We analyze real-time user interactions, including mouse movements (speed, acceleration, straightness), typing rhythm (keystroke latency, dwell, and flight times), and click precision (coordinate variance). These metrics reveal whether an interaction is genuinely human or robotically precise.
|
|
43
|
+
* **Benefit**: Identify and block sophisticated bots that attempt to mimic human behavior, protecting your applications from automated fraud, account takeovers, and content manipulation.
|
|
44
|
+
|
|
45
|
+
### 5. ๐ Cross-Layer & Analog Inconsistency Scoring: Expose Advanced Spoofing
|
|
46
|
+
* **Problem**: Bots often try to fake their identity across different layers of their connection, leading to inconsistencies that traditional security systems miss.
|
|
47
|
+
* **Solution**: Our engine cross-references information from various layers (User-Agent, Client Hints, TLS, TCP stack) to detect subtle discrepancies. For example, a client claiming to be a Windows browser but exhibiting a Linux TCP stack will be flagged.
|
|
48
|
+
* **Benefit**: Catch advanced spoofing attempts that bypass single-layer detection, providing a more robust defense against sophisticated attackers.
|
|
49
|
+
|
|
50
|
+
### 6. ๐ Federated Threat Intelligence & Peer Sharing: Immunize Your Network Instantly
|
|
51
|
+
* **Problem**: Isolated servers are vulnerable to distributed attacks, learning about new malicious actors only after being hit and compromised.
|
|
52
|
+
* **Solution**: Our decentralized gossip protocol securely synchronizes cryptographically signed, privacy-compliant threat intelligence (ZKP public keys) with trusted peer networks in real-time. If an attacker is blocked on one federated node, they are instantly blacklisted across all nodes.
|
|
53
|
+
* **Benefit**: Leverage collective defense. Your system is immunized against active botnets before they even attempt to target your servers.
|
|
54
|
+
|
|
55
|
+
### 7. ๐ธ๏ธ Coordinated Botnet Clustering: Neutralize IP-Rotation Tactics
|
|
56
|
+
* **Problem**: Modern botnets rotate thousands of clean, residential proxy IPs to easily bypass traditional IP-based reputation lists and standard rate limiters.
|
|
57
|
+
* **Solution**: The engine clusters and profiles incoming requests using highly stable, non-volatile hardware invariants (such as combinations of JA3/JA4, TCP, and GPU hashes). Multiple requests sharing the exact same hardware footprint across distinct IPs within a rolling window are grouped and treated as a single coordinated botnet.
|
|
58
|
+
* **Benefit**: Defeat distributed scraping and credential stuffing campaigns, making expensive residential proxy rotation completely useless for attackers.
|
|
59
|
+
|
|
60
|
+
### 8. ๐ฆ Honeypot Traps & Extensible WAF: Instantly Condemn Malicious Actors
|
|
61
|
+
* **Problem**: Malicious bots and vulnerability scanners often probe for hidden fields or sensitive URLs, but traditional defenses only react after an attack has occurred.
|
|
62
|
+
* **Solution**: We deploy invisible traps (hidden form fields, signed trap URLs) that only bots interact with. Any interaction with these honeypots immediately triggers a maximum suspicion score, leading to instant blocking. Our extensible WAF also detects common injection attempts (SQLi, XSS, RCE).
|
|
63
|
+
* **Benefit**: Proactively identify and block malicious actors at the earliest stage of their attack, preventing data breaches, spam, and system exploitation.
|
|
64
|
+
### 9. ๐งฌ Progressive Threshold Auto-Tuning: Adapt Your Defenses Automatically
|
|
65
|
+
* **Problem**: Threat landscapes constantly evolve, requiring continuous manual adjustments to security settings, which is time-consuming and prone to human error.
|
|
66
|
+
* **Solution**: Our engine uses a genetic algorithm to continuously optimize your security parameters (weights, thresholds, patterns) in the background, based on real-world traffic data. It learns to distinguish between legitimate users and bots, adapting your defenses in real-time.
|
|
67
|
+
* **Benefit**: Maintain optimal protection without constant manual intervention. Your security posture automatically adapts to new threats and traffic patterns, ensuring maximum effectiveness and minimal false positives.
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
|
|
71
|
+
### Node.js
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm install @anonympins/fingerprint
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### PHP
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
composer require anonympins/fingerprint
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Python
|
|
84
|
+
```bash
|
|
85
|
+
pip install fingerprint-engine
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Documentation
|
|
89
|
+
|
|
90
|
+
To prevent documentation drift, all detailed guides and reference materials are maintained in the `doc/` directory. Please refer to [these resources](https://github.com/anonympins/fingerprint/wiki/home) to configure and integrate the engine:
|
|
91
|
+
|
|
92
|
+
1. **[Key Concepts & Suspicion Vectors](https://github.com/anonympins/fingerprint/wiki/concepts)**: Learn how the engine calculates suspicion scores across the 15 distinct vectors and manages the Proof-of-Work mitigation layers.
|
|
93
|
+
2. **[Node.js Integration Guide](https://github.com/anonympins/fingerprint/wiki/nodejs_integration)**: Step-by-step instructions for Express.js middleware and raw HTTP server integrations.
|
|
94
|
+
3. **[PHP Integration Guide](https://github.com/anonympins/fingerprint/wiki/php_integration)**: Configuration details for direct PHP integration, TLS fingerprinting forwarding via Nginx/Apache, and securing Prometheus metrics.
|
|
95
|
+
4. **[Python Integration Guide](https://github.com/anonympins/fingerprint/wiki/python_integration)**: Python middleware for ASGI and WSGI integration.
|
|
96
|
+
5. **[Java Integration Guide](https://github.com/anonympins/fingerprint/wiki/java_integration)**: Java library (Servlet, Spring WebFlux)
|
|
97
|
+
6. **[Full Configuration Options](https://github.com/anonympins/fingerprint/wiki/full_options)**: Complete parameter list for fine-tuning weights, custom honeypots, and security profile overrides.
|
|
98
|
+
7. **[API Reference](https://github.com/anonympins/fingerprint/wiki/api_reference)**: Public API signatures and guides on substituting the in-memory datastore with Redis or MongoDB.
|
|
99
|
+
|
|
100
|
+
Start with the **[Documentation Portal](https://github.com/anonympins/fingerprint/wiki/home)** for a complete index.
|
|
101
|
+
|
|
102
|
+
## Contributing
|
|
103
|
+
|
|
104
|
+
We welcome community contributions! Please read our **[Contributing Guidelines](https://github.com/anonympins/fingerprint/blob/main/CONTRIBUTING.md)** for information on:
|
|
105
|
+
- Setting up your local environment (Node.js and PHP).
|
|
106
|
+
- Running the test suites (`Vitest` and `PHPUnit`).
|
|
107
|
+
- Coding and pull request standards.
|
|
108
|
+
|
|
109
|
+
Thanks to our contributors :
|
|
110
|
+
- [anonympins](https://github.com/anonympins)
|
|
111
|
+
|
|
112
|
+
## ๐ Sponsor This Project
|
|
113
|
+
|
|
114
|
+
If this security suite helps protect your business against botnets, automated scraping, credential stuffing, or Layer 7 DDoS attacks, please consider supporting its active development!
|
|
115
|
+
|
|
116
|
+
Sponsorship helps maintain the library, fund active updates, and keep the dynamic WebAssembly engine cutting-edge.
|
|
117
|
+
|
|
118
|
+
**Want to be featured here?** You can also become a sponsor and get your logo displayed in this section simply by running Fingerprint in production on your platforms!
|
|
119
|
+
|
|
120
|
+
### ๐ Featured Sponsors
|
|
121
|
+
|
|
122
|
+
<img src="https://s6.imgcdn.dev/YJTWv9.png" width="100" alt="YJTWv9.png" border="0" valign="middle">
|
|
123
|
+
|
|
124
|
+
[https://primals.net](https://primals.net) and sub-sites
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
120
129
|
This project is licensed under the MIT License.
|
package/composer.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anonympins/fingerprint",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "Advanced anti-bot library for Node.js using multi-layer fingerprinting (JA3, client-side, headers), behavioral analysis, and adaptive Proof-of-Work (PoW) challenges to mitigate scraping, scalping, and automated threats.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
package/public/fp.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var createFingerprintModule=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var programArgs=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}programArgs=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var isFileURI=filename=>filename.startsWith("file://");class EmscriptenEH{}class EmscriptenSjLj extends EmscriptenEH{}var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAPU8=new Uint8Array(b);HEAPU32=new Uint32Array(b)}function preRun(){var preRun=Module["preRun"];if(preRun){if(typeof preRun=="function")preRun=[preRun];onPreRuns.push(...preRun)}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["e"]()}function postRun(){var postRun=Module["postRun"];if(postRun){if(typeof postRun=="function")postRun=[postRun];onPostRuns.push(...postRun)}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what=`Aborted(${what})`;err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("fp.wasm")}function getBinarySync(file){if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();var instantiateWasm=Module["instantiateWasm"];if(instantiateWasm){return new Promise(resolve=>{instantiateWasm(info,inst=>resolve(receiveInstance(inst)))})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var onPreRuns=[];var noExitRuntime=true;var HEAP8;var HEAPU32;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var uncaughtExceptionCount=0;var __Unwind_RaiseException=ex=>{abort()};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);uncaughtExceptionCount++;__Unwind_RaiseException(ptr)};var __abort_js=()=>abort("");var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var HEAPU8;var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["arguments"])programArgs=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var preInit=Module["preInit"];if(preInit){if(typeof preInit=="function")Module["preInit"]=preInit=[preInit];while(preInit.length>0){preInit.shift()()}}}var _hash_string,_solve_cpu_target,_solve_memory_challenge,memory,__indirect_function_table,wasmMemory;function assignWasmExports(wasmExports){_hash_string=Module["_hash_string"]=wasmExports["f"];_solve_cpu_target=Module["_solve_cpu_target"]=wasmExports["g"];_solve_memory_challenge=Module["_solve_memory_challenge"]=wasmExports["h"];memory=wasmMemory=wasmExports["d"];__indirect_function_table=wasmExports["__indirect_function_table"]}var wasmImports={c:___cxa_throw,a:__abort_js,b:_emscripten_resize_heap};async function run(){preRun();var setStatus=Module["setStatus"];if(setStatus){setStatus("Running...");await new Promise(resolve=>setTimeout(resolve,1));setTimeout(setStatus,1,"")}if(ABORT)return;initRuntime();Module["onRuntimeInitialized"]?.();postRun()}var wasmExports;wasmExports=await createWasm();await run();
|
|
1
|
+
var createFingerprintModule=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var programArgs=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}programArgs=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var isFileURI=filename=>filename.startsWith("file://");class EmscriptenEH{}class EmscriptenSjLj extends EmscriptenEH{}var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAPU8=new Uint8Array(b);HEAPU32=new Uint32Array(b)}function preRun(){var preRun=Module["preRun"];if(preRun){if(typeof preRun=="function")preRun=[preRun];onPreRuns.push(...preRun)}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["e"]()}function postRun(){var postRun=Module["postRun"];if(postRun){if(typeof postRun=="function")postRun=[postRun];onPostRuns.push(...postRun)}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what=`Aborted(${what})`;err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("fp.wasm")}function getBinarySync(file){if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();var instantiateWasm=Module["instantiateWasm"];if(instantiateWasm){return new Promise(resolve=>{instantiateWasm(info,inst=>resolve(receiveInstance(inst)))})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var onPreRuns=[];var noExitRuntime=true;var HEAP8;var HEAPU32;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var uncaughtExceptionCount=0;var __Unwind_RaiseException=ex=>{abort()};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);uncaughtExceptionCount++;__Unwind_RaiseException(ptr)};var __abort_js=()=>abort("");var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var HEAPU8;var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["arguments"])programArgs=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var preInit=Module["preInit"];if(preInit){if(typeof preInit=="function")Module["preInit"]=preInit=[preInit];while(preInit.length>0){preInit.shift()()}}}var _hash_string,_solve_cpu_target,_solve_memory_challenge,_generate_gpu_pow_trajectory,memory,__indirect_function_table,wasmMemory;function assignWasmExports(wasmExports){_hash_string=Module["_hash_string"]=wasmExports["f"];_solve_cpu_target=Module["_solve_cpu_target"]=wasmExports["g"];_solve_memory_challenge=Module["_solve_memory_challenge"]=wasmExports["h"];_generate_gpu_pow_trajectory=Module["_generate_gpu_pow_trajectory"]=wasmExports["i"];memory=wasmMemory=wasmExports["d"];__indirect_function_table=wasmExports["__indirect_function_table"]}var wasmImports={c:___cxa_throw,a:__abort_js,b:_emscripten_resize_heap};async function run(){preRun();var setStatus=Module["setStatus"];if(setStatus){setStatus("Running...");await new Promise(resolve=>setTimeout(resolve,1));setTimeout(setStatus,1,"")}if(ABORT)return;initRuntime();Module["onRuntimeInitialized"]?.();postRun()}var wasmExports;wasmExports=await createWasm();await run();
|
|
2
2
|
;return Module}})();if(typeof exports==="object"&&typeof module==="object"){module.exports=createFingerprintModule;module.exports.default=createFingerprintModule}else if(typeof define==="function"&&define["amd"])define([],()=>createFingerprintModule);
|
package/public/fp.wasm
CHANGED
|
Binary file
|
package/src/js/build-client.js
CHANGED
|
@@ -14,7 +14,7 @@ const __dirname = dirname(__filename);
|
|
|
14
14
|
function buildWasm() {
|
|
15
15
|
return new Promise((resolve) => {
|
|
16
16
|
console.log('Attempting to build WASM module (optional)...');
|
|
17
|
-
const command = "em++ src/cpp/main.cpp src/cpp/utils.cpp -o public/fp.js -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME='createFingerprintModule' -s \"EXPORTED_FUNCTIONS=['_hash_string','_solve_cpu_target','_solve_memory_challenge','_generate_gpu_pow_trajectory']\" -O3 --no-entry";
|
|
17
|
+
const command = "em++ src/cpp/main.cpp src/cpp/utils.cpp -o public/fp.js -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME='createFingerprintModule' -s \"EXPORTED_FUNCTIONS=['_malloc','_free','_hash_string','_solve_cpu_target','_solve_memory_challenge','_generate_gpu_pow_trajectory']\" -O3 --no-entry";
|
|
18
18
|
|
|
19
19
|
exec(command, (error, stdout, stderr) => {
|
|
20
20
|
if (error) {
|
|
@@ -921,9 +921,11 @@ const ClientLibrary = {
|
|
|
921
921
|
async protectedFetch(resource, options = {}) {
|
|
922
922
|
const fp = this.getDeviceFingerprint();
|
|
923
923
|
const rawBehavior = this.getClientBehaviorMetrics();
|
|
924
|
+
const zkpProof = await this.generateZkpProof(fp); // Generate ZKP proof
|
|
924
925
|
const behavior = await signMetrics(rawBehavior);
|
|
925
926
|
|
|
926
927
|
const headers = new Headers(options.headers || {});
|
|
928
|
+
headers.set('X-ZKP-Proof', zkpProof); // Add ZKP proof to headers
|
|
927
929
|
headers.set('X-Device-Fingerprint', fp);
|
|
928
930
|
headers.set('X-Behavior-Metrics', JSON.stringify(behavior));
|
|
929
931
|
|