@anonympins/fingerprint 0.5.5 → 0.6.1
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 +21 -0
- package/README.md +7 -6
- 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 +19 -5
- package/src/js/fingerprint.client.obfuscated.js +1 -1
- package/src/js/fingerprint.js +430 -74
- package/src/js/problem-manager.js +22 -0
- package/src/js/tests/cross_parity.test.js +17 -11
- package/src/js/tests/fingerprint.client.test.js +130 -128
- package/src/js/tests/fingerprint.test.js +17 -2
- package/src/js/ttl-optimization.worker.js +51 -0
- package/src/php/Challenge/ChallengeUtils.php +120 -8
- package/src/php/FingerprintBuilder.php +193 -185
- package/src/php/FingerprintEngine.php +245 -3
- package/src/php/ProblemManager.php +20 -0
- package/src/php/RequestContext.php +2 -0
- package/src/php/Tests/ChallengeUtilsTest.php +446 -285
- package/src/php/Utils/RequestUtils.php +26 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## Version 0.6.1
|
|
2
|
+
|
|
3
|
+
- **🔑 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.
|
|
4
|
+
- **🛡️ 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).
|
|
5
|
+
- **🌐 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).
|
|
6
|
+
- **How it works**:
|
|
7
|
+
1. **Peer Discovery & Secure Handshake**: Nodes register and establish cryptographically signed, peer-to-peer secure handshakes with adjacent trust boundaries.
|
|
8
|
+
2. **Decentralized Threat Gossip Protocol**: High-confidence threat signals, subnet reputation blocks, and poisoned hardware fingerprints are shared instantly across federated peers.
|
|
9
|
+
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.
|
|
10
|
+
4. **Symmetric Trust Verification**: Prevents rogue peers from falsely whitelisting botnets through a multi-signature validation mechanism.
|
|
11
|
+
- **⚡ 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.
|
|
12
|
+
- **🧹 Active Peer Table Pruning**: Standardized and automated the garbage collection of offline or unresponsive federated nodes to protect local memory structures from exhaustion.
|
|
13
|
+
- **📖 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.
|
|
14
|
+
|
|
15
|
+
## Version 0.6.0
|
|
16
|
+
|
|
17
|
+
- **🛡️ 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).
|
|
18
|
+
- **⚡ Math Optimizations & TTL Worker**: Optimized performance for 64-bit integers and the `cyrb53` hashing implementation on PHP 7+, reducing CPU overhead. Integrated automated background TTL optimization worker execution (Contributed by @anonympins).
|
|
19
|
+
- **🧹 IP Pruning**: Standardized and optimized IP pruning and rate-limiting data lifecycles to prevent memory exhaustion and leaks during high-concurrency scraping attempts (Contributed by @anonympins).
|
|
20
|
+
- Java integration (see README and wiki)
|
|
21
|
+
|
|
1
22
|
## Version 0.5.5
|
|
2
23
|
|
|
3
24
|
- **🔒 Client Session Handshake & HMAC Metric Signing**: Implemented elliptic-curve Diffie-Hellman (ECDH over curve `P-256`) key exchange protocol during client initialization (`?fp_handshake=1`). Leveraged the negotiated session key to cryptographically sign behavioral metrics (`signMetrics`) on the client using HMAC-SHA256, protecting against replay attacks and telemetry tampering.
|
package/README.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Fingerprint anti-bot protection
|
|
2
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-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
4
|
|
|
5
5
|
[](https://github.com/anonympins/fingerprint/releases)
|
|
6
6
|
[](https://github.com/anonympins/fingerprint/blob/main/LICENSE)
|
|
7
7
|
[](https://github.com/anonympins/fingerprint/commits/main)
|
|
8
8
|
[](https://github.com/anonympins/fingerprint)
|
|
9
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**, **Python** and **PHP** environments.
|
|
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
11
|
|
|
12
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
13
|
|
|
14
|
-
Supported officially on **Node.js (>=20.0.0)**, **PHP (>=8.0)**, and **Python (>=3.8)**.
|
|
14
|
+
Supported officially on **Node.js (>=20.0.0)**, **PHP (>=8.0)**, Java (>=17), and **Python (>=3.8)**.
|
|
15
15
|
|
|
16
16
|

|
|
17
17
|
|
|
@@ -85,9 +85,10 @@ To prevent documentation drift, all detailed guides and reference materials are
|
|
|
85
85
|
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.
|
|
86
86
|
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.
|
|
87
87
|
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.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
4. **[Python Integration Guide](https://github.com/anonympins/fingerprint/wiki/python_integration)**: Python middleware for ASGI and WSGI integration.
|
|
89
|
+
5. **[Java Integration Guide](https://github.com/anonympins/fingerprint/wiki/java_integration)**: Java library (Servlet, Spring WebFlux)
|
|
90
|
+
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.
|
|
91
|
+
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.
|
|
91
92
|
|
|
92
93
|
Start with the **[Documentation Portal](https://github.com/anonympins/fingerprint/wiki/home)** for a complete index.
|
|
93
94
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anonympins/fingerprint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
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
|
|
|
@@ -1340,11 +1342,23 @@ const ClientLibrary = {
|
|
|
1340
1342
|
window.wasmModule = wasmModule;
|
|
1341
1343
|
ClientLibrary.wasmModule = wasmModule;
|
|
1342
1344
|
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1345
|
+
// Pooling de mémoire statique : pré-allocation d'un buffer réutilisable de 4 Ko
|
|
1346
|
+
// Évite d'allouer/libérer de la mémoire sur le tas Emscripten lors des frappes clavier/mouvements souris rapides
|
|
1347
|
+
const staticBufferSize = 4096;
|
|
1348
|
+
const staticBufferPtr = wasmModule._malloc(staticBufferSize);
|
|
1349
|
+
const encoder = new TextEncoder();
|
|
1350
|
+
|
|
1351
|
+
// 4. Remplacer la fonction de hachage par la version WASM optimisée via le buffer statique
|
|
1352
|
+
activeCyrb53 = (str) => {
|
|
1353
|
+
const bytes = encoder.encode(str);
|
|
1354
|
+
if (bytes.length < staticBufferSize) {
|
|
1355
|
+
wasmModule.HEAPU8.set(bytes, staticBufferPtr);
|
|
1356
|
+
wasmModule.HEAPU8[staticBufferPtr + bytes.length] = 0; // null-terminator
|
|
1357
|
+
return wasmModule._hash_string(staticBufferPtr);
|
|
1358
|
+
}
|
|
1359
|
+
// Fallback dynamique sécurisé si la chaîne dépasse la taille du buffer statique
|
|
1360
|
+
return wasmModule._hash_string(str);
|
|
1361
|
+
};
|
|
1348
1362
|
|
|
1349
1363
|
console.log('[Fingerprint] WASM module loaded successfully. Using fast hashing.');
|
|
1350
1364
|
// NOUVEAU: Ajoute un indicateur à l'empreinte pour que le serveur sache que le WASM est actif.
|