@anonympins/fingerprint 0.7.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/public/anonympins-bot-mitigation-pow.zip +0 -0
- package/src/js/dynamic-wasm.js +218 -218
- package/src/js/fingerprint.client.js +1784 -1738
- package/src/js/fingerprint.client.obfuscated.js +1 -1
- package/src/js/fingerprint.js +489 -99
- package/src/js/fingerprint.utils.js +252 -2
- package/src/js/pow.worker.js +2 -2
- package/src/js/tests/cross_parity.test.js +3 -3
- package/src/js/tests/dns-circuit-breaker.test.js +6 -6
- package/src/js/tests/dynamic-wasm.test.js +77 -77
- package/src/js/tests/fingerprint.builder.test.js +76 -78
- package/src/js/tests/fingerprint.client.init.test.js +78 -0
- package/src/js/tests/fingerprint.client.test.js +16 -17
- package/src/js/tests/fingerprint.test.js +37 -12
- package/src/js/tests/ja3AnomalyDetector.test.js +135 -136
- package/src/js/tests/library.test.js +94 -95
- package/src/js/tests/obfuscation.test.js +8 -8
- package/src/js/tests/quicFingerprint.test.js +47 -0
- package/src/js/tests/tcpFingerprint.test.js +4 -4
- package/src/js/tests/threatIntel.test.js +40 -1
- package/src/js/upow-model-task.js +155 -112
- package/src/php/Challenge/ChallengeUtils.php +392 -86
- package/src/php/Config/SecurityProfiles.php +79 -61
- package/src/php/DirectFingerprint.php +55 -8
- package/src/php/FingerprintBuilder.php +13 -13
- package/src/php/FingerprintClient.php +6 -6
- package/src/php/FingerprintEngine.php +2122 -1690
- package/src/php/Ja3AnomalyDetector.php +22 -22
- package/src/php/Optimization/FunctionRegistry.php +4 -4
- package/src/php/Optimization/Optimization.php +6 -6
- package/src/php/RequestContext.php +11 -11
- package/src/php/Store/InMemoryStore.php +96 -66
- package/src/php/Store/MongoDbStore.php +2 -2
- package/src/php/Store/RedisStore.php +1 -1
- package/src/php/Store/StoreManager.php +48 -35
- package/src/php/Tests/ChallengeUtilsTest.php +31 -0
- package/src/php/Tests/DnsCircuitBreakerTest.php +105 -105
- package/src/php/Tests/FingerprintClientTest.php +70 -70
- package/src/php/Tests/PowTest.php +37 -39
- package/src/php/Tests/QuicFingerprintTest.php +115 -53
- package/src/php/Tests/ThreatIntelTest.php +34 -0
- package/src/php/Utils/BigInt.php +202 -202
- package/src/php/Utils/BlockList.php +13 -13
- package/src/php/Utils/Logger.php +19 -1
- package/src/php/Utils/MaliciousPatterns.php +6 -6
- package/src/php/Utils/MetricsManager.php +209 -209
- package/src/php/Utils/RequestUtils.php +362 -1
- package/src/php/Utils/TLSClientHelloParser.php +385 -369
- package/src/php/WordPress/WpDbStore.php +7 -7
- package/src/php/WordPress/anonympins-bot-mitigation-pow.php +1121 -0
- package/src/php/WordPress/fingerprint-anti-bot.php +0 -559
- package/src/php/WordPress/languages/anonympins-bot-mitigation-pow-fr_FR.mo +0 -0
- package/src/php/WordPress/languages/anonympins-bot-mitigation-pow-fr_FR.po +232 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.mo +0 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.po +297 -261
- package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.mo +0 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.po +348 -267
- package/src/php/WordPress/package.php +80 -101
- package/src/php/WordPress/readme.txt +21 -5
- package/src/php/bin/auto-tune.php +1 -1
- package/public/fingerprint-anti-bot.zip +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it } from 'vitest';
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import { __internal, configureStore } from '../fingerprint.js';
|
|
3
3
|
|
|
4
4
|
describe('Threat Intelligence - Rationale-Driven Defensive Logic', () => {
|
|
@@ -73,4 +73,43 @@ describe('Threat Intelligence - Rationale-Driven Defensive Logic', () => {
|
|
|
73
73
|
expect(vector.threatIntelScore).toBeGreaterThan(70.0);
|
|
74
74
|
expect(vector.threatIntelScore).toBeLessThanOrEqual(95.0);
|
|
75
75
|
});
|
|
76
|
+
|
|
77
|
+
it('should broadcast banned ZKP with differential privacy (perturbed timestamps and decoy injection)', async () => {
|
|
78
|
+
const calls = [];
|
|
79
|
+
const originalFetch = globalThis.fetch;
|
|
80
|
+
globalThis.fetch = vi.fn(async (url, init) => {
|
|
81
|
+
calls.push({ url, init });
|
|
82
|
+
return { ok: true, json: async () => ({ status: 'synchronized' }) };
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const config = {
|
|
86
|
+
federatedPeers: ['https://peer1.example.com', 'https://peer2.example.com'],
|
|
87
|
+
federationSecret: 'test-secret-key-32-chars-long!!',
|
|
88
|
+
differentialPrivacy: {
|
|
89
|
+
enabled: true,
|
|
90
|
+
epsilon: 1.0,
|
|
91
|
+
dummyRate: 1.0 // Force decoy generation for deterministic testing
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const realZkpY = 'deadbeef12345678';
|
|
96
|
+
await __internal.broadcastBannedZkp(realZkpY, config);
|
|
97
|
+
|
|
98
|
+
// Should broadcast to 2 peers with real key + 2 peers with decoy key
|
|
99
|
+
expect(calls.length).toBe(4);
|
|
100
|
+
|
|
101
|
+
const bodies = calls.map(c => JSON.parse(c.init.body));
|
|
102
|
+
const zkpYs = bodies.map(b => b.zkpY);
|
|
103
|
+
|
|
104
|
+
expect(zkpYs).toContain(realZkpY);
|
|
105
|
+
const decoyKey = zkpYs.find(k => k !== realZkpY);
|
|
106
|
+
expect(decoyKey).toBeDefined();
|
|
107
|
+
expect(decoyKey).not.toBe(realZkpY);
|
|
108
|
+
|
|
109
|
+
for (const call of calls) {
|
|
110
|
+
const timestamp = Number(call.init.headers['X-Federation-Timestamp']);
|
|
111
|
+
expect(timestamp).toBeGreaterThan(0);
|
|
112
|
+
}
|
|
113
|
+
globalThis.fetch = originalFetch;
|
|
114
|
+
});
|
|
76
115
|
});
|
|
@@ -1,113 +1,156 @@
|
|
|
1
|
-
import crypto from "node:crypto";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Abstract base class defining useful Proof-of-Work (uPoW) tasks based on ML training
|
|
5
|
-
* or inference validation (e.g. PyTorch models exported to ONNX format).
|
|
6
|
-
*/
|
|
7
|
-
export class UpowModelTask {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class defining useful Proof-of-Work (uPoW) tasks based on ML training
|
|
5
|
+
* or inference validation (e.g. PyTorch models exported to ONNX format).
|
|
6
|
+
*/
|
|
7
|
+
export class UpowModelTask {
|
|
8
|
+
/**
|
|
9
|
+
* Creates a new UpowModelTask. This class is abstract and cannot be
|
|
10
|
+
* instantiated directly.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} problemId - The unique identifier of the problem.
|
|
13
|
+
* @param {string} modelPath - The network asset path of the model.
|
|
14
|
+
* @param {object} [config={}] - Optional configuration overrides.
|
|
15
|
+
* @param {number} [config.batchSize=32] - Mini-batch size.
|
|
16
|
+
* @param {number} [config.learningRate=0.01] - Learning rate.
|
|
17
|
+
* @param {number} [config.validationTolerance=0.15] - Validation tolerance.
|
|
18
|
+
* @throws {TypeError} If instantiated directly.
|
|
19
|
+
*/
|
|
20
|
+
constructor(problemId, modelPath, config = {}) {
|
|
21
|
+
if (new.target === UpowModelTask) {
|
|
22
|
+
throw new TypeError("Cannot construct UpowModelTask instances directly");
|
|
23
|
+
}
|
|
24
|
+
this.problemId = problemId;
|
|
25
|
+
this.modelPath = modelPath;
|
|
26
|
+
this.config = {
|
|
27
|
+
batchSize: 32,
|
|
28
|
+
learningRate: 0.01,
|
|
29
|
+
validationTolerance: 0.15,
|
|
30
|
+
...config
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns the unique problem identifier.
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
getProblemId() {
|
|
39
|
+
return this.problemId;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Returns the network asset path of the model.
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
getModelAssetPath() {
|
|
47
|
+
return this.modelPath;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Dispatches task workload to the client.
|
|
52
|
+
* Transmits current model weights and mini-batch sample data.
|
|
53
|
+
* @param {number} suspicionFactor
|
|
54
|
+
* @returns {object} Task payload dispatched to client
|
|
55
|
+
*/
|
|
56
|
+
dispatchTask(suspicionFactor) {
|
|
57
|
+
throw new Error("Method 'dispatchTask(suspicionFactor)' must be implemented.");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Validates solution returned by the client.
|
|
62
|
+
* Implements anti-poisoning guards and gradient bounds checks.
|
|
63
|
+
* @param {object} taskContext
|
|
64
|
+
* @param {object} solution
|
|
65
|
+
* @returns {boolean}
|
|
66
|
+
*/
|
|
67
|
+
verifySolution(taskContext, solution) {
|
|
68
|
+
throw new Error("Method 'verifySolution(taskContext, solution)' must be implemented.");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Integrates validated gradients into global model weights (e.g. FedAvg).
|
|
73
|
+
* @param {object} solution
|
|
74
|
+
*/
|
|
75
|
+
integrateSolution(solution) {
|
|
76
|
+
throw new Error("Method 'integrateSolution(solution)' must be implemented.");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Example training task implementation (suspicious request classifier).
|
|
82
|
+
*/
|
|
83
|
+
export class RequestClassifierTask extends UpowModelTask {
|
|
84
|
+
/**
|
|
85
|
+
* Creates a new RequestClassifierTask with an initial set of linear
|
|
86
|
+
* neural network weights.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} modelPath - The network asset path of the model.
|
|
89
|
+
* @param {object} config - Configuration object (batch size, learning rate, etc.).
|
|
90
|
+
*/
|
|
91
|
+
constructor(modelPath, config) {
|
|
92
|
+
super("request_classifier_nn", modelPath, config);
|
|
93
|
+
// Initial model weights (linear neural network)
|
|
94
|
+
this.weights = [0.1, -0.2, 0.8, 0.5];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Builds and returns the task payload sent to the client, including the
|
|
99
|
+
* current model weights, an anonymized sample training batch, the learning
|
|
100
|
+
* rate, and the batch size.
|
|
101
|
+
*
|
|
102
|
+
* @param {number} suspicionFactor - The suspicion factor for this request.
|
|
103
|
+
* @returns {object} The task payload dispatched to the client.
|
|
104
|
+
*/
|
|
105
|
+
dispatchTask(suspicionFactor) {
|
|
106
|
+
// Anonymized sample training batch dispatched to client
|
|
107
|
+
const inputs = [
|
|
108
|
+
[1.0, 0.5, 0.0, 1.2],
|
|
109
|
+
[0.0, 1.0, -0.5, 0.8]
|
|
110
|
+
];
|
|
111
|
+
return {
|
|
112
|
+
weights: [...this.weights],
|
|
113
|
+
inputs: inputs,
|
|
114
|
+
learningRate: this.config.learningRate,
|
|
115
|
+
batchSize: this.config.batchSize
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Validates the solution returned by the client. Ensures the gradients
|
|
121
|
+
* array has the expected length and applies an anti-poisoning guard by
|
|
122
|
+
* rejecting any gradient whose absolute value exceeds a fixed threshold
|
|
123
|
+
* (gradient clipping).
|
|
124
|
+
*
|
|
125
|
+
* @param {object} taskContext - The context of the dispatched task.
|
|
126
|
+
* @param {object} solution - The solution returned by the client.
|
|
127
|
+
* @returns {boolean} True if the solution is valid, false otherwise.
|
|
128
|
+
*/
|
|
129
|
+
verifySolution(taskContext, solution) {
|
|
130
|
+
const gradients = solution?.gradients;
|
|
131
|
+
if (!Array.isArray(gradients) || gradients.length !== this.weights.length) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
// Anti-poisoning guard: ensure gradients do not exceed threshold norms (gradient clipping)
|
|
135
|
+
const maxGradientNorm = 10.0;
|
|
136
|
+
for (const grad of gradients) {
|
|
137
|
+
if (typeof grad !== 'number' || isNaN(grad) || Math.abs(grad) > maxGradientNorm) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Integrates the validated gradients into the global model weights using
|
|
146
|
+
* a simple gradient descent update: w_i -= learningRate * grad_i.
|
|
147
|
+
*
|
|
148
|
+
* @param {object} solution - The validated solution containing gradients.
|
|
149
|
+
*/
|
|
150
|
+
integrateSolution(solution) {
|
|
151
|
+
const gradients = solution.gradients;
|
|
152
|
+
for (let i = 0; i < this.weights.length; i++) {
|
|
153
|
+
this.weights[i] -= this.config.learningRate * gradients[i];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
113
156
|
}
|