@lightharu/krouter 1.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/LICENSE +679 -0
- package/README.md +238 -0
- package/dist-web/assets/index-CM4-0adf.css +1 -0
- package/dist-web/assets/index-DCslvfUR.js +139 -0
- package/dist-web/favicon.svg +9 -0
- package/dist-web/icon.svg +9 -0
- package/dist-web/index.html +19 -0
- package/out-server/main/kiroAuthSync.js +249 -0
- package/out-server/main/kproxy/certManager.js +262 -0
- package/out-server/main/kproxy/index.js +254 -0
- package/out-server/main/kproxy/mitmProxy.js +475 -0
- package/out-server/main/kproxy/types.js +23 -0
- package/out-server/main/proxy/accountPool.js +543 -0
- package/out-server/main/proxy/clientConfig.js +596 -0
- package/out-server/main/proxy/index.js +25 -0
- package/out-server/main/proxy/kiroApi.js +1996 -0
- package/out-server/main/proxy/logger.js +407 -0
- package/out-server/main/proxy/modelCatalog.js +75 -0
- package/out-server/main/proxy/promptCacheTracker.js +301 -0
- package/out-server/main/proxy/proxyServer.js +3543 -0
- package/out-server/main/proxy/selfSignedCert.js +179 -0
- package/out-server/main/proxy/systemProxy.js +250 -0
- package/out-server/main/proxy/tokenCounter.js +164 -0
- package/out-server/main/proxy/toolNameRegistry.js +57 -0
- package/out-server/main/proxy/translator.js +1084 -0
- package/out-server/main/proxy/types.js +3 -0
- package/out-server/main/registration/browser-identity.js +184 -0
- package/out-server/main/registration/chainProxy.js +349 -0
- package/out-server/main/registration/config.js +58 -0
- package/out-server/main/registration/email-service.js +801 -0
- package/out-server/main/registration/fingerprint.js +352 -0
- package/out-server/main/registration/http-utils.js +148 -0
- package/out-server/main/registration/jwe.js +74 -0
- package/out-server/main/registration/names.js +142 -0
- package/out-server/main/registration/proton-mail-window.js +339 -0
- package/out-server/main/registration/registrar.js +1715 -0
- package/out-server/main/registration/tlsClientPool.js +70 -0
- package/out-server/main/registration/xxtea.js +161 -0
- package/out-server/main/runtimePaths.js +19 -0
- package/out-server/main/utils/redact.js +95 -0
- package/out-server/server/index.js +1272 -0
- package/out-server/server/services/accountExtras.js +105 -0
- package/out-server/server/services/accountProfileHydration.js +95 -0
- package/out-server/server/services/authFlows.js +509 -0
- package/out-server/server/services/dashboardTunnel.js +315 -0
- package/out-server/server/services/diagnostics.js +326 -0
- package/out-server/server/services/kiroAccounts.js +431 -0
- package/out-server/server/services/kiroSettings.js +260 -0
- package/out-server/server/services/kproxyRuntime.js +264 -0
- package/out-server/server/services/localKiroCredentials.js +320 -0
- package/out-server/server/services/machineIdRuntime.js +327 -0
- package/out-server/server/services/protonBrowserRuntime.js +724 -0
- package/out-server/server/services/proxyRuntime.js +523 -0
- package/out-server/server/services/registrationRuntime.js +106 -0
- package/out-server/server/store.js +266 -0
- package/package.json +113 -0
- package/resources/tls-client-xgo-1.14.0-windows-amd64.dll +0 -0
- package/scripts/kiro-manager-cli.cjs +3 -0
- package/scripts/krouter-cli.cjs +509 -0
- package/src/renderer/src/assets/krouter-logo.svg +11 -0
- package/src/renderer/src/assets/krouter-mark.svg +9 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OrderedMap = void 0;
|
|
4
|
+
exports.newFPContext = newFPContext;
|
|
5
|
+
exports.resetPerfTiming = resetPerfTiming;
|
|
6
|
+
exports.buildFingerprintData = buildFingerprintData;
|
|
7
|
+
exports.generateFingerprint = generateFingerprint;
|
|
8
|
+
const xxtea_1 = require("./xxtea");
|
|
9
|
+
function randInt(max) {
|
|
10
|
+
return Math.floor(Math.random() * max);
|
|
11
|
+
}
|
|
12
|
+
function crc32Str(str) {
|
|
13
|
+
let crc = 0xffffffff >>> 0;
|
|
14
|
+
const table = getCrc32Table();
|
|
15
|
+
for (let i = 0; i < str.length; i++) {
|
|
16
|
+
crc = ((crc >>> 8) ^ table[(crc ^ str.charCodeAt(i)) & 0xff]) >>> 0;
|
|
17
|
+
}
|
|
18
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
19
|
+
}
|
|
20
|
+
let _t = null;
|
|
21
|
+
function getCrc32Table() {
|
|
22
|
+
if (_t)
|
|
23
|
+
return _t;
|
|
24
|
+
_t = new Uint32Array(256);
|
|
25
|
+
for (let i = 0; i < 256; i++) {
|
|
26
|
+
let c = i >>> 0;
|
|
27
|
+
for (let j = 0; j < 8; j++)
|
|
28
|
+
c = c & 1 ? (0xedb88320 ^ (c >>> 1)) >>> 0 : c >>> 1;
|
|
29
|
+
_t[i] = c;
|
|
30
|
+
}
|
|
31
|
+
return _t;
|
|
32
|
+
}
|
|
33
|
+
// ============ OrderedMap ============
|
|
34
|
+
class OrderedMap {
|
|
35
|
+
keys = [];
|
|
36
|
+
values = new Map();
|
|
37
|
+
set(key, value) {
|
|
38
|
+
if (!this.values.has(key))
|
|
39
|
+
this.keys.push(key);
|
|
40
|
+
this.values.set(key, value);
|
|
41
|
+
}
|
|
42
|
+
toJSON() {
|
|
43
|
+
const parts = [];
|
|
44
|
+
for (const k of this.keys) {
|
|
45
|
+
parts.push(`${JSON.stringify(k)}:${JSON.stringify(this.values.get(k))}`);
|
|
46
|
+
}
|
|
47
|
+
return `{${parts.join(',')}}`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.OrderedMap = OrderedMap;
|
|
51
|
+
function newFPContext(identity) {
|
|
52
|
+
const ts = Math.floor(Date.now() / 1000);
|
|
53
|
+
return {
|
|
54
|
+
identity,
|
|
55
|
+
canvasHash: identity.canvasHash,
|
|
56
|
+
histogramBins: [...identity.histogramBase],
|
|
57
|
+
lsUbidSignin: `${identity.lsubidPrefixSignin}-${String(randInt(10000000)).padStart(7, '0')}-${String(randInt(10000000)).padStart(7, '0')}:${ts}`,
|
|
58
|
+
lsUbidProfile: '',
|
|
59
|
+
perfTiming: null,
|
|
60
|
+
startTime: null
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function resetPerfTiming(ctx) {
|
|
64
|
+
ctx.perfTiming = null;
|
|
65
|
+
}
|
|
66
|
+
function genPerfTiming(nowMs) {
|
|
67
|
+
const loadEventEnd = nowMs - (500 + randInt(1001));
|
|
68
|
+
const loadDuration = 2000 + randInt(2001);
|
|
69
|
+
const base = loadEventEnd - loadDuration;
|
|
70
|
+
const dnsOffset = 2 + randInt(8);
|
|
71
|
+
const connectEndOffset = 300 + randInt(300);
|
|
72
|
+
const responseOffset = connectEndOffset + 200 + randInt(400);
|
|
73
|
+
const domInteractiveOffset = loadDuration - (5 + randInt(11));
|
|
74
|
+
const domContentLoadedStart = domInteractiveOffset + randInt(3);
|
|
75
|
+
return {
|
|
76
|
+
connectStart: base + dnsOffset + 1 + randInt(3),
|
|
77
|
+
secureConnectionStart: base + dnsOffset + 3 + randInt(5),
|
|
78
|
+
unloadEventEnd: 0,
|
|
79
|
+
domainLookupStart: base + dnsOffset,
|
|
80
|
+
domainLookupEnd: base + dnsOffset + randInt(2),
|
|
81
|
+
responseStart: base + responseOffset,
|
|
82
|
+
connectEnd: base + connectEndOffset,
|
|
83
|
+
responseEnd: base + responseOffset + randInt(5),
|
|
84
|
+
requestStart: base + connectEndOffset,
|
|
85
|
+
domLoading: base + responseOffset + 2 + randInt(5),
|
|
86
|
+
redirectStart: 0,
|
|
87
|
+
loadEventEnd,
|
|
88
|
+
domComplete: loadEventEnd,
|
|
89
|
+
navigationStart: base,
|
|
90
|
+
loadEventStart: loadEventEnd,
|
|
91
|
+
domContentLoadedEventEnd: loadEventEnd,
|
|
92
|
+
unloadEventStart: 0,
|
|
93
|
+
redirectEnd: 0,
|
|
94
|
+
domInteractive: base + domInteractiveOffset,
|
|
95
|
+
fetchStart: base + dnsOffset,
|
|
96
|
+
domContentLoadedEventStart: base + domContentLoadedStart
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function getPerfTiming(ctx, nowMs) {
|
|
100
|
+
if (!ctx.perfTiming)
|
|
101
|
+
ctx.perfTiming = genPerfTiming(nowMs);
|
|
102
|
+
return ctx.perfTiming;
|
|
103
|
+
}
|
|
104
|
+
function getLsUbid(ctx, pageType) {
|
|
105
|
+
if (pageType === 'profile') {
|
|
106
|
+
if (!ctx.lsUbidProfile) {
|
|
107
|
+
const ts = ctx.perfTiming
|
|
108
|
+
? Math.floor(ctx.perfTiming.loadEventEnd / 1000)
|
|
109
|
+
: Math.floor(Date.now() / 1000);
|
|
110
|
+
ctx.lsUbidProfile = `${ctx.identity.lsubidPrefixProfile}-${String(randInt(10000000)).padStart(7, '0')}-${String(randInt(10000000)).padStart(7, '0')}:${ts}`;
|
|
111
|
+
}
|
|
112
|
+
return ctx.lsUbidProfile;
|
|
113
|
+
}
|
|
114
|
+
return ctx.lsUbidSignin;
|
|
115
|
+
}
|
|
116
|
+
function getStartTime(ctx, nowMs) {
|
|
117
|
+
if (ctx.startTime === null)
|
|
118
|
+
ctx.startTime = nowMs;
|
|
119
|
+
return ctx.startTime;
|
|
120
|
+
}
|
|
121
|
+
// ============ Metrics & Interaction ============
|
|
122
|
+
function genMetricsFirstLoad(pageType) {
|
|
123
|
+
const m = {
|
|
124
|
+
el: 0, script: 0, h: 0, batt: 0, perf: 0, auto: 0,
|
|
125
|
+
tz: 0, fp2: 0, lsubid: 0, browser: 0, capabilities: 0,
|
|
126
|
+
gpu: 0, dnt: 0, math: 0, tts: 0, input: 0, canvas: 0,
|
|
127
|
+
captchainput: 0, pow: 0
|
|
128
|
+
};
|
|
129
|
+
switch (pageType) {
|
|
130
|
+
case 'profile':
|
|
131
|
+
m.batt = 5 + randInt(21);
|
|
132
|
+
m.fp2 = 1 + randInt(8);
|
|
133
|
+
m.browser = randInt(4);
|
|
134
|
+
m.capabilities = 1 + randInt(8);
|
|
135
|
+
m.dnt = randInt(4);
|
|
136
|
+
m.input = 8 + randInt(23);
|
|
137
|
+
m.canvas = 5 + randInt(16);
|
|
138
|
+
break;
|
|
139
|
+
case 'signup':
|
|
140
|
+
m.script = randInt(3);
|
|
141
|
+
m.batt = randInt(6);
|
|
142
|
+
m.fp2 = randInt(4);
|
|
143
|
+
m.gpu = 3 + randInt(6);
|
|
144
|
+
break;
|
|
145
|
+
default:
|
|
146
|
+
m.script = randInt(3);
|
|
147
|
+
m.auto = randInt(3);
|
|
148
|
+
m.browser = randInt(3);
|
|
149
|
+
m.gpu = 3 + randInt(6);
|
|
150
|
+
}
|
|
151
|
+
return m;
|
|
152
|
+
}
|
|
153
|
+
function genMetricsPageSubmit() {
|
|
154
|
+
return {
|
|
155
|
+
el: 0, script: 0, h: 0, batt: 0, perf: randInt(3),
|
|
156
|
+
auto: 0, tz: 0, fp2: 0, lsubid: 0, browser: 0,
|
|
157
|
+
capabilities: 0, gpu: 0, dnt: 0, math: 0, tts: 0,
|
|
158
|
+
input: 0, canvas: 0, captchainput: 0, pow: 0
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function genInteraction(eventType) {
|
|
162
|
+
if (eventType === 'PageLoad' || eventType === 'first_load') {
|
|
163
|
+
return {
|
|
164
|
+
clicks: 0, touches: 0, keyPresses: 0,
|
|
165
|
+
cuts: 0, copies: 0, pastes: 0,
|
|
166
|
+
keyPressTimeIntervals: [], mouseClickPositions: [],
|
|
167
|
+
keyCycles: [], mouseCycles: [], touchCycles: []
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const nClicks = 1 + randInt(3);
|
|
171
|
+
const nKeys = 3 + randInt(8);
|
|
172
|
+
const nIntervals = Math.max(1, Math.floor(nKeys / 3)) + randInt(Math.max(1, Math.floor(nKeys / 2) - Math.floor(nKeys / 3) + 1));
|
|
173
|
+
const nCycles = Math.max(2, Math.floor(nKeys / 2)) + randInt(Math.max(1, Math.floor(nKeys * 2 / 3) - Math.floor(nKeys / 2) + 1));
|
|
174
|
+
return {
|
|
175
|
+
clicks: nClicks, touches: 0, keyPresses: nKeys,
|
|
176
|
+
cuts: 0, copies: 0, pastes: 0,
|
|
177
|
+
keyPressTimeIntervals: Array.from({ length: nIntervals }, () => 80 + randInt(621)),
|
|
178
|
+
mouseClickPositions: Array.from({ length: nClicks }, () => `${400 + randInt(401)},${300 + randInt(201)}`),
|
|
179
|
+
keyCycles: Array.from({ length: nCycles }, () => 20 + randInt(281)),
|
|
180
|
+
mouseCycles: Array.from({ length: nClicks }, () => 50 + randInt(101)),
|
|
181
|
+
touchCycles: []
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function genFormField(startMs, emailLen, email, interaction) {
|
|
185
|
+
const fieldTs = startMs - (10 + randInt(41));
|
|
186
|
+
const fieldRand = 1000 + randInt(9000);
|
|
187
|
+
const fieldName = `formField29-${fieldTs}-${fieldRand}`;
|
|
188
|
+
let nKeys = Math.max(3, Math.floor(emailLen / 3) + randInt(5) - 2);
|
|
189
|
+
const intervals = Array.from({ length: Math.min(nKeys - 1, 5) }, () => 80 + randInt(621));
|
|
190
|
+
const keyCycles = Array.from({ length: Math.min(nKeys, 6) }, () => 20 + randInt(231));
|
|
191
|
+
if (typeof interaction.keyPresses === 'number' && interaction.keyPresses > 0) {
|
|
192
|
+
nKeys = interaction.keyPresses;
|
|
193
|
+
}
|
|
194
|
+
const checksumStr = email || `user${1000 + randInt(9000)}@example.com`;
|
|
195
|
+
const cksum = crc32Str(checksumStr).toString(16).toUpperCase().padStart(8, '0');
|
|
196
|
+
return {
|
|
197
|
+
[fieldName]: {
|
|
198
|
+
clicks: 1, touches: 0, keyPresses: nKeys,
|
|
199
|
+
cuts: 0, copies: 0, pastes: 0,
|
|
200
|
+
keyPressTimeIntervals: intervals,
|
|
201
|
+
mouseClickPositions: [`${100 + randInt(151)}.5,${10 + randInt(11)}.5`],
|
|
202
|
+
keyCycles, mouseCycles: [80 + randInt(71)], touchCycles: [],
|
|
203
|
+
width: 180, height: 32, totalFocusTime: 0,
|
|
204
|
+
checksum: cksum, autocomplete: false, prefilled: false
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// ============ Build Fingerprint ============
|
|
209
|
+
function formatScreen(s) {
|
|
210
|
+
return `${s.width}-${s.height}-${s.availHeight}-${s.colorDepth}-*-*-*`;
|
|
211
|
+
}
|
|
212
|
+
function formatPlugins(plugins) {
|
|
213
|
+
return plugins.map((p) => p.name).join(' ');
|
|
214
|
+
}
|
|
215
|
+
function buildFingerprintData(identity, locationURL, referrer, nowMs, ctx, pageType, eventType, timeOnPage, emailLen, email) {
|
|
216
|
+
const canvasHash = ctx ? ctx.canvasHash : identity.canvasHash;
|
|
217
|
+
const histogram = ctx ? ctx.histogramBins : identity.histogramBase;
|
|
218
|
+
const perfTiming = ctx ? getPerfTiming(ctx, nowMs) : genPerfTiming(nowMs);
|
|
219
|
+
let lsUbid;
|
|
220
|
+
if (ctx) {
|
|
221
|
+
lsUbid = getLsUbid(ctx, pageType);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
lsUbid = `${identity.lsubidPrefixSignin}-${String(randInt(10000000)).padStart(7, '0')}-${String(randInt(10000000)).padStart(7, '0')}:${Math.floor(perfTiming.loadEventEnd / 1000)}`;
|
|
225
|
+
}
|
|
226
|
+
let dynamicURLs;
|
|
227
|
+
let scriptsElapsed;
|
|
228
|
+
let historyLength;
|
|
229
|
+
let isCompatible;
|
|
230
|
+
switch (pageType) {
|
|
231
|
+
case 'profile':
|
|
232
|
+
dynamicURLs = [`/dist/main/app_${identity.webpackHash}.min.js`];
|
|
233
|
+
scriptsElapsed = 0;
|
|
234
|
+
historyLength = (eventType === 'PageLoad' || eventType === 'first_load') ? 2 : 3;
|
|
235
|
+
isCompatible = true;
|
|
236
|
+
break;
|
|
237
|
+
case 'signup':
|
|
238
|
+
dynamicURLs = ['/assets/js/app.js'];
|
|
239
|
+
scriptsElapsed = 1;
|
|
240
|
+
historyLength = 5;
|
|
241
|
+
isCompatible = true;
|
|
242
|
+
break;
|
|
243
|
+
default:
|
|
244
|
+
dynamicURLs = ['/assets/js/app.js'];
|
|
245
|
+
scriptsElapsed = 1;
|
|
246
|
+
historyLength = 1;
|
|
247
|
+
isCompatible = false;
|
|
248
|
+
}
|
|
249
|
+
let metrics;
|
|
250
|
+
if (eventType === 'first_load' || (eventType === 'PageLoad' && pageType === 'profile')) {
|
|
251
|
+
metrics = genMetricsFirstLoad(pageType);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
metrics = genMetricsPageSubmit();
|
|
255
|
+
}
|
|
256
|
+
const interaction = genInteraction(eventType);
|
|
257
|
+
const endMs = nowMs + randInt(51);
|
|
258
|
+
let startTime;
|
|
259
|
+
if (eventType !== 'PageLoad' && eventType !== 'first_load' && timeOnPage > 0) {
|
|
260
|
+
startTime = endMs - timeOnPage;
|
|
261
|
+
}
|
|
262
|
+
else if (ctx) {
|
|
263
|
+
if (eventType === 'first_load') {
|
|
264
|
+
startTime = getStartTime(ctx, nowMs - (500 + randInt(501)));
|
|
265
|
+
}
|
|
266
|
+
else if (eventType === 'PageLoad' && pageType === 'profile') {
|
|
267
|
+
startTime = getStartTime(ctx, nowMs - (30 + randInt(51)));
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
startTime = getStartTime(ctx, nowMs);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
startTime = nowMs;
|
|
275
|
+
}
|
|
276
|
+
const pluginsStr = formatPlugins(identity.plugins);
|
|
277
|
+
const screenStr = formatScreen(identity.screen);
|
|
278
|
+
const result = new OrderedMap();
|
|
279
|
+
result.set('metrics', metrics);
|
|
280
|
+
result.set('start', startTime);
|
|
281
|
+
result.set('interaction', interaction);
|
|
282
|
+
result.set('scripts', {
|
|
283
|
+
dynamicUrls: dynamicURLs, inlineHashes: [],
|
|
284
|
+
elapsed: scriptsElapsed, dynamicUrlCount: dynamicURLs.length, inlineHashesCount: 0
|
|
285
|
+
});
|
|
286
|
+
result.set('history', { length: historyLength });
|
|
287
|
+
result.set('battery', {});
|
|
288
|
+
result.set('performance', { timing: perfTiming });
|
|
289
|
+
result.set('automation', {
|
|
290
|
+
wd: { properties: { document: [], window: [], navigator: [] } },
|
|
291
|
+
phantom: { properties: { window: [] } }
|
|
292
|
+
});
|
|
293
|
+
result.set('end', endMs);
|
|
294
|
+
result.set('timeZone', 8);
|
|
295
|
+
result.set('flashVersion', null);
|
|
296
|
+
result.set('plugins', pluginsStr + ' ||' + screenStr);
|
|
297
|
+
result.set('dupedPlugins', pluginsStr + ' ||' + screenStr);
|
|
298
|
+
result.set('screenInfo', screenStr);
|
|
299
|
+
result.set('lsUbid', lsUbid);
|
|
300
|
+
result.set('referrer', referrer);
|
|
301
|
+
result.set('userAgent', identity.ua);
|
|
302
|
+
result.set('location', locationURL);
|
|
303
|
+
result.set('webDriver', false);
|
|
304
|
+
result.set('capabilities', {
|
|
305
|
+
css: {
|
|
306
|
+
textShadow: 1, WebkitTextStroke: 1, boxShadow: 1,
|
|
307
|
+
borderRadius: 1, borderImage: 1, opacity: 1,
|
|
308
|
+
transform: 1, transition: 1
|
|
309
|
+
},
|
|
310
|
+
js: {
|
|
311
|
+
audio: true, geolocation: true, localStorage: 'supported',
|
|
312
|
+
touch: false, video: true, webWorker: true
|
|
313
|
+
},
|
|
314
|
+
elapsed: 0
|
|
315
|
+
});
|
|
316
|
+
result.set('gpu', {
|
|
317
|
+
vendor: identity.gpuVendor, model: identity.gpuModel,
|
|
318
|
+
extensions: identity.webGLExts
|
|
319
|
+
});
|
|
320
|
+
result.set('dnt', null);
|
|
321
|
+
result.set('math', { tan: identity.mathTan, sin: identity.mathSin, cos: identity.mathCos });
|
|
322
|
+
if (pageType === 'profile') {
|
|
323
|
+
if (eventType === 'PageLoad' || eventType === 'first_load') {
|
|
324
|
+
result.set('timeToSubmit', 1 + randInt(5));
|
|
325
|
+
}
|
|
326
|
+
else if (timeOnPage > 0) {
|
|
327
|
+
result.set('timeToSubmit', timeOnPage);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
result.set('timeToSubmit', 2000 + randInt(4001));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (pageType === 'profile' && eventType !== 'PageLoad' && eventType !== 'first_load' && emailLen > 0) {
|
|
334
|
+
result.set('form', genFormField(nowMs, emailLen, email, interaction));
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
result.set('form', {});
|
|
338
|
+
}
|
|
339
|
+
result.set('canvas', { hash: canvasHash, emailHash: null, histogramBins: [...histogram] });
|
|
340
|
+
result.set('token', { isCompatible, pageHasCaptcha: 0 });
|
|
341
|
+
result.set('auth', { form: { method: 'get' } });
|
|
342
|
+
result.set('errors', []);
|
|
343
|
+
result.set('version', (0, xxtea_1.getTESVersion)());
|
|
344
|
+
return result;
|
|
345
|
+
}
|
|
346
|
+
/** 生成加密后的浏览器指纹字符串 */
|
|
347
|
+
function generateFingerprint(identity, locationURL, referrer, ctx, pageType, eventType, timeOnPage, emailLen, email) {
|
|
348
|
+
const nowMs = Date.now();
|
|
349
|
+
const fpData = buildFingerprintData(identity, locationURL, referrer, nowMs, ctx, pageType, eventType, timeOnPage, emailLen, email);
|
|
350
|
+
const jsonStr = fpData.toJSON();
|
|
351
|
+
return (0, xxtea_1.encryptFingerprint)(jsonStr);
|
|
352
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DEFAULT_SEC_UA = exports.DEFAULT_UA = void 0;
|
|
7
|
+
exports.visitorId = visitorId;
|
|
8
|
+
exports.awsccc = awsccc;
|
|
9
|
+
exports.ubidGen = ubidGen;
|
|
10
|
+
exports.kiroVisitorId = kiroVisitorId;
|
|
11
|
+
exports.pkce = pkce;
|
|
12
|
+
exports.newUUID = newUUID;
|
|
13
|
+
exports.gmtDate = gmtDate;
|
|
14
|
+
exports.extractParam = extractParam;
|
|
15
|
+
exports.splitAfter = splitAfter;
|
|
16
|
+
exports.getNestedMap = getNestedMap;
|
|
17
|
+
exports.getNestedStringMap = getNestedStringMap;
|
|
18
|
+
exports.saveCookies = saveCookies;
|
|
19
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
20
|
+
exports.DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36';
|
|
21
|
+
exports.DEFAULT_SEC_UA = '"Chromium";v="146", "Not/A)Brand";v="24", "Google Chrome";v="146"';
|
|
22
|
+
/** 生成 4 位随机十六进制 */
|
|
23
|
+
function hex4() {
|
|
24
|
+
const chars = '0123456789abcdef';
|
|
25
|
+
let s = '';
|
|
26
|
+
for (let i = 0; i < 4; i++)
|
|
27
|
+
s += chars[Math.floor(Math.random() * 16)];
|
|
28
|
+
return s;
|
|
29
|
+
}
|
|
30
|
+
/** 生成随机 visitor ID (UUID v4-like) */
|
|
31
|
+
function visitorId() {
|
|
32
|
+
return `${hex4()}${hex4()}-${hex4()}-7${hex4().slice(1)}-${hex4()}-${hex4()}${hex4()}${hex4()}`;
|
|
33
|
+
}
|
|
34
|
+
/** 生成 awsccc cookie 值 */
|
|
35
|
+
function awsccc() {
|
|
36
|
+
const d = {
|
|
37
|
+
e: 1,
|
|
38
|
+
p: 1,
|
|
39
|
+
f: 1,
|
|
40
|
+
a: 1,
|
|
41
|
+
i: `${hex4()}${hex4()}-${hex4()}-4${hex4().slice(1)}-${hex4()}-${hex4()}${hex4()}${hex4()}`,
|
|
42
|
+
v: '1'
|
|
43
|
+
};
|
|
44
|
+
return Buffer.from(JSON.stringify(d)).toString('base64');
|
|
45
|
+
}
|
|
46
|
+
/** 生成 ubid cookie 值 */
|
|
47
|
+
function ubidGen() {
|
|
48
|
+
const d7 = Array.from({ length: 7 }, () => Math.floor(Math.random() * 10)).join('');
|
|
49
|
+
const d6 = Array.from({ length: 6 }, () => Math.floor(Math.random() * 10)).join('');
|
|
50
|
+
return `186-${d7}-${d6}`;
|
|
51
|
+
}
|
|
52
|
+
/** 生成 Kiro visitor ID */
|
|
53
|
+
function kiroVisitorId() {
|
|
54
|
+
const chars = '0123456789abcdefghijklmnopqrstuvwxyz';
|
|
55
|
+
let s = '';
|
|
56
|
+
for (let i = 0; i < 11; i++)
|
|
57
|
+
s += chars[Math.floor(Math.random() * chars.length)];
|
|
58
|
+
return `${Date.now()}-${s}`;
|
|
59
|
+
}
|
|
60
|
+
/** 生成 PKCE code_verifier 和 code_challenge */
|
|
61
|
+
function pkce() {
|
|
62
|
+
const raw = crypto_1.default.randomBytes(32);
|
|
63
|
+
const verifier = raw.toString('base64url');
|
|
64
|
+
const hash = crypto_1.default.createHash('sha256').update(verifier).digest();
|
|
65
|
+
const challenge = hash.toString('base64url');
|
|
66
|
+
return { verifier, challenge };
|
|
67
|
+
}
|
|
68
|
+
/** 生成 UUID */
|
|
69
|
+
function newUUID() {
|
|
70
|
+
const b = crypto_1.default.randomBytes(16);
|
|
71
|
+
return [
|
|
72
|
+
b.subarray(0, 4).toString('hex'),
|
|
73
|
+
b.subarray(4, 6).toString('hex'),
|
|
74
|
+
b.subarray(6, 8).toString('hex'),
|
|
75
|
+
b.subarray(8, 10).toString('hex'),
|
|
76
|
+
b.subarray(10, 16).toString('hex')
|
|
77
|
+
].join('-');
|
|
78
|
+
}
|
|
79
|
+
/** 生成 GMT 日期字符串 */
|
|
80
|
+
function gmtDate() {
|
|
81
|
+
return new Date().toUTCString();
|
|
82
|
+
}
|
|
83
|
+
/** 从 URL 中提取查询参数 */
|
|
84
|
+
function extractParam(rawURL, key) {
|
|
85
|
+
try {
|
|
86
|
+
const u = new URL(rawURL);
|
|
87
|
+
return u.searchParams.get(key) || '';
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return '';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/** 从字符串中提取分隔符后的内容 */
|
|
94
|
+
function splitAfter(s, sep) {
|
|
95
|
+
const idx = s.indexOf(sep);
|
|
96
|
+
if (idx < 0)
|
|
97
|
+
return '';
|
|
98
|
+
const rest = s.slice(idx + sep.length);
|
|
99
|
+
const ampIdx = rest.indexOf('&');
|
|
100
|
+
return ampIdx >= 0 ? rest.slice(0, ampIdx) : rest;
|
|
101
|
+
}
|
|
102
|
+
/** 获取嵌套 map 值 */
|
|
103
|
+
function getNestedMap(data, ...keys) {
|
|
104
|
+
let current = data;
|
|
105
|
+
for (const k of keys) {
|
|
106
|
+
if (typeof current !== 'object' || current === null)
|
|
107
|
+
return null;
|
|
108
|
+
current = current[k];
|
|
109
|
+
}
|
|
110
|
+
return typeof current === 'object' && current !== null
|
|
111
|
+
? current
|
|
112
|
+
: null;
|
|
113
|
+
}
|
|
114
|
+
/** 获取嵌套的 string map */
|
|
115
|
+
function getNestedStringMap(data, key) {
|
|
116
|
+
if (!data)
|
|
117
|
+
return null;
|
|
118
|
+
const nested = data[key];
|
|
119
|
+
if (typeof nested !== 'object' || nested === null)
|
|
120
|
+
return null;
|
|
121
|
+
const result = {};
|
|
122
|
+
for (const [k, v] of Object.entries(nested)) {
|
|
123
|
+
if (typeof v === 'string')
|
|
124
|
+
result[k] = v;
|
|
125
|
+
}
|
|
126
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
127
|
+
}
|
|
128
|
+
/** 从 Set-Cookie 头中提取并保存 cookies */
|
|
129
|
+
function saveCookies(cookies, headers) {
|
|
130
|
+
const skip = new Set(['path', 'domain', 'expires', 'max-age', 'secure', 'httponly', 'samesite']);
|
|
131
|
+
const setCookieHeader = headers['set-cookie'];
|
|
132
|
+
if (!setCookieHeader)
|
|
133
|
+
return;
|
|
134
|
+
const values = Array.isArray(setCookieHeader) ? setCookieHeader : [setCookieHeader];
|
|
135
|
+
for (const raw of values) {
|
|
136
|
+
if (!raw.includes('='))
|
|
137
|
+
continue;
|
|
138
|
+
const mainPart = raw.split(';')[0];
|
|
139
|
+
const eqIdx = mainPart.indexOf('=');
|
|
140
|
+
if (eqIdx < 0)
|
|
141
|
+
continue;
|
|
142
|
+
const k = mainPart.slice(0, eqIdx).trim();
|
|
143
|
+
const v = mainPart.slice(eqIdx + 1).trim();
|
|
144
|
+
if (!skip.has(k.toLowerCase()) && k) {
|
|
145
|
+
cookies.set(k, v);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.encryptPassword = encryptPassword;
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
function b64url(data) {
|
|
9
|
+
return data.toString('base64url');
|
|
10
|
+
}
|
|
11
|
+
function jwkToPublicKey(jwk) {
|
|
12
|
+
const n = Buffer.from(jwk.n, 'base64url');
|
|
13
|
+
const e = Buffer.from(jwk.e, 'base64url');
|
|
14
|
+
return crypto_1.default.createPublicKey({
|
|
15
|
+
key: {
|
|
16
|
+
kty: 'RSA',
|
|
17
|
+
n: n.toString('base64url'),
|
|
18
|
+
e: e.toString('base64url')
|
|
19
|
+
},
|
|
20
|
+
format: 'jwk'
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function genUUID() {
|
|
24
|
+
const b = crypto_1.default.randomBytes(16);
|
|
25
|
+
return [
|
|
26
|
+
b.subarray(0, 4).toString('hex'),
|
|
27
|
+
b.subarray(4, 6).toString('hex'),
|
|
28
|
+
b.subarray(6, 8).toString('hex'),
|
|
29
|
+
b.subarray(8, 10).toString('hex'),
|
|
30
|
+
b.subarray(10, 16).toString('hex')
|
|
31
|
+
].join('-');
|
|
32
|
+
}
|
|
33
|
+
/** JWE 加密密码 (RSA-OAEP-256 + A256GCM) */
|
|
34
|
+
function encryptPassword(password, publicKey, issuer, audience, region) {
|
|
35
|
+
// Header
|
|
36
|
+
const header = {
|
|
37
|
+
alg: 'RSA-OAEP-256',
|
|
38
|
+
kid: publicKey.kid,
|
|
39
|
+
enc: 'A256GCM',
|
|
40
|
+
cty: 'enc',
|
|
41
|
+
typ: 'application/aws+signin+jwe'
|
|
42
|
+
};
|
|
43
|
+
const headerJSON = Buffer.from(JSON.stringify(header));
|
|
44
|
+
const headerB64 = b64url(headerJSON);
|
|
45
|
+
// CEK (内容加密密钥)
|
|
46
|
+
const cek = crypto_1.default.randomBytes(32);
|
|
47
|
+
// RSA-OAEP-256 加密 CEK
|
|
48
|
+
const pubKey = jwkToPublicKey(publicKey);
|
|
49
|
+
const encryptedCEK = crypto_1.default.publicEncrypt({
|
|
50
|
+
key: pubKey,
|
|
51
|
+
padding: crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING,
|
|
52
|
+
oaepHash: 'sha256'
|
|
53
|
+
}, cek);
|
|
54
|
+
// Claims
|
|
55
|
+
const now = Math.floor(Date.now() / 1000);
|
|
56
|
+
const claims = {
|
|
57
|
+
iss: `${region}.${issuer}`,
|
|
58
|
+
iat: now,
|
|
59
|
+
nbf: now,
|
|
60
|
+
jti: genUUID(),
|
|
61
|
+
exp: now + 300,
|
|
62
|
+
aud: `${region}.${audience}`,
|
|
63
|
+
password
|
|
64
|
+
};
|
|
65
|
+
const plaintext = Buffer.from(JSON.stringify(claims));
|
|
66
|
+
// AES-256-GCM 加密
|
|
67
|
+
const iv = crypto_1.default.randomBytes(12);
|
|
68
|
+
const cipher = crypto_1.default.createCipheriv('aes-256-gcm', cek, iv, { authTagLength: 16 });
|
|
69
|
+
cipher.setAAD(Buffer.from(headerB64, 'ascii'));
|
|
70
|
+
const ct = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
71
|
+
const tag = cipher.getAuthTag();
|
|
72
|
+
// JWE Compact: header.encKey.iv.ciphertext.tag
|
|
73
|
+
return `${headerB64}.${b64url(encryptedCEK)}.${b64url(iv)}.${b64url(ct)}.${b64url(tag)}`;
|
|
74
|
+
}
|