meshcore-hashtag-cracker 1.0.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.
@@ -0,0 +1,358 @@
1
+ /**
2
+ * GroupTextCracker - Standalone MeshCore GroupText packet cracker
3
+ *
4
+ * Cracks encrypted GroupText packets by trying room names until the
5
+ * correct encryption key is found.
6
+ */
7
+ import { MeshCorePacketDecoder, ChannelCrypto } from '@michaelhart/meshcore-decoder';
8
+ import { GpuBruteForce, isWebGpuSupported } from './gpu-bruteforce';
9
+ import { CpuBruteForce } from './cpu-bruteforce';
10
+ import { PUBLIC_ROOM_NAME, PUBLIC_KEY, DEFAULT_VALID_SECONDS, indexToRoomName, roomNameToIndex, deriveKeyFromRoomName, getChannelHash, verifyMac, countNamesForLength, isTimestampValid, isValidUtf8, } from './core';
11
+ // Valid room name characters (for wordlist filtering)
12
+ const VALID_CHARS = /^[a-z0-9-]+$/;
13
+ const NO_DASH_AT_ENDS = /^[a-z0-9].*[a-z0-9]$|^[a-z0-9]$/;
14
+ const NO_CONSECUTIVE_DASHES = /--/;
15
+ function isValidRoomName(name) {
16
+ if (!name || name.length === 0)
17
+ return false;
18
+ if (!VALID_CHARS.test(name))
19
+ return false;
20
+ if (name.length > 1 && !NO_DASH_AT_ENDS.test(name))
21
+ return false;
22
+ if (NO_CONSECUTIVE_DASHES.test(name))
23
+ return false;
24
+ return true;
25
+ }
26
+ /**
27
+ * Main cracker class for MeshCore GroupText packets.
28
+ */
29
+ export class GroupTextCracker {
30
+ constructor() {
31
+ this.gpuInstance = null;
32
+ this.cpuInstance = null;
33
+ this.wordlist = [];
34
+ this.abortFlag = false;
35
+ this.useTimestampFilter = true;
36
+ this.useUtf8Filter = true;
37
+ this.validSeconds = DEFAULT_VALID_SECONDS;
38
+ this.useCpu = false;
39
+ }
40
+ /**
41
+ * Load a wordlist from a URL for dictionary attacks.
42
+ * The wordlist should be a text file with one word per line.
43
+ *
44
+ * @param url - URL to fetch the wordlist from
45
+ */
46
+ async loadWordlist(url) {
47
+ const response = await fetch(url);
48
+ if (!response.ok) {
49
+ throw new Error(`Failed to load wordlist: ${response.status} ${response.statusText}`);
50
+ }
51
+ const text = await response.text();
52
+ const allWords = text
53
+ .split('\n')
54
+ .map((w) => w.trim().toLowerCase())
55
+ .filter((w) => w.length > 0);
56
+ // Filter to valid room names only
57
+ this.wordlist = allWords.filter(isValidRoomName);
58
+ }
59
+ /**
60
+ * Set the wordlist directly from an array of words.
61
+ *
62
+ * @param words - Array of room names to try
63
+ */
64
+ setWordlist(words) {
65
+ this.wordlist = words
66
+ .map((w) => w.trim().toLowerCase())
67
+ .filter(isValidRoomName);
68
+ }
69
+ /**
70
+ * Abort the current cracking operation.
71
+ * The crack() method will return with aborted: true.
72
+ */
73
+ abort() {
74
+ this.abortFlag = true;
75
+ }
76
+ /**
77
+ * Check if WebGPU is available in the current environment.
78
+ */
79
+ isGpuAvailable() {
80
+ return isWebGpuSupported();
81
+ }
82
+ /**
83
+ * Decode a packet and extract the information needed for cracking.
84
+ *
85
+ * @param packetHex - The packet data as a hex string
86
+ * @returns Decoded packet info or null if not a GroupText packet
87
+ */
88
+ async decodePacket(packetHex) {
89
+ const cleanHex = packetHex.trim().replace(/\s+/g, '').replace(/^0x/i, '');
90
+ if (!cleanHex || !/^[0-9a-fA-F]+$/.test(cleanHex)) {
91
+ return null;
92
+ }
93
+ try {
94
+ const decoded = await MeshCorePacketDecoder.decodeWithVerification(cleanHex, {});
95
+ const payload = decoded.payload?.decoded;
96
+ if (!payload?.channelHash || !payload?.ciphertext || !payload?.cipherMac) {
97
+ return null;
98
+ }
99
+ return {
100
+ channelHash: payload.channelHash,
101
+ ciphertext: payload.ciphertext,
102
+ cipherMac: payload.cipherMac,
103
+ isGroupText: true,
104
+ };
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ /**
111
+ * Crack a GroupText packet to find the room name and decrypt the message.
112
+ *
113
+ * @param packetHex - The packet data as a hex string
114
+ * @param options - Cracking options
115
+ * @param onProgress - Optional callback for progress updates
116
+ * @returns The cracking result
117
+ */
118
+ async crack(packetHex, options, onProgress) {
119
+ this.abortFlag = false;
120
+ this.useTimestampFilter = options?.useTimestampFilter ?? true;
121
+ this.useUtf8Filter = options?.useUtf8Filter ?? true;
122
+ this.validSeconds = options?.validSeconds ?? DEFAULT_VALID_SECONDS;
123
+ this.useCpu = options?.forceCpu ?? false;
124
+ const maxLength = options?.maxLength ?? 8;
125
+ const startingLength = options?.startingLength ?? 1;
126
+ const useDictionary = options?.useDictionary ?? true;
127
+ // Decode packet
128
+ const decoded = await this.decodePacket(packetHex);
129
+ if (!decoded) {
130
+ return { found: false, error: 'Invalid packet or not a GroupText packet' };
131
+ }
132
+ const { channelHash, ciphertext, cipherMac } = decoded;
133
+ const targetHashByte = parseInt(channelHash, 16);
134
+ // Initialize GPU or CPU instance
135
+ if (this.useCpu) {
136
+ // Use CPU fallback
137
+ if (!this.cpuInstance) {
138
+ this.cpuInstance = new CpuBruteForce();
139
+ }
140
+ }
141
+ else {
142
+ // Try GPU, fall back to CPU if not available
143
+ if (!this.gpuInstance) {
144
+ this.gpuInstance = new GpuBruteForce();
145
+ const gpuOk = await this.gpuInstance.init();
146
+ if (!gpuOk) {
147
+ // GPU not available, fall back to CPU
148
+ this.useCpu = true;
149
+ this.cpuInstance = new CpuBruteForce();
150
+ }
151
+ }
152
+ }
153
+ const startTime = performance.now();
154
+ let totalChecked = 0;
155
+ let lastProgressUpdate = performance.now();
156
+ // Determine starting position
157
+ let startFromLength = startingLength;
158
+ let startFromOffset = 0;
159
+ if (options?.startFrom) {
160
+ const pos = roomNameToIndex(options.startFrom);
161
+ if (pos) {
162
+ startFromLength = Math.max(startingLength, pos.length);
163
+ startFromOffset = pos.index + 1; // Start after the given position
164
+ if (startFromOffset >= countNamesForLength(startFromLength)) {
165
+ startFromLength++;
166
+ startFromOffset = 0;
167
+ }
168
+ }
169
+ }
170
+ // Calculate total candidates for progress
171
+ let totalCandidates = 0;
172
+ for (let l = startFromLength; l <= maxLength; l++) {
173
+ totalCandidates += countNamesForLength(l);
174
+ }
175
+ totalCandidates -= startFromOffset;
176
+ // Helper to report progress
177
+ const reportProgress = (phase, currentLength, currentPosition) => {
178
+ if (!onProgress)
179
+ return;
180
+ const now = performance.now();
181
+ const elapsed = (now - startTime) / 1000;
182
+ const rate = elapsed > 0 ? Math.round(totalChecked / elapsed) : 0;
183
+ const remaining = totalCandidates - totalChecked;
184
+ const eta = rate > 0 ? remaining / rate : 0;
185
+ onProgress({
186
+ checked: totalChecked,
187
+ total: totalCandidates,
188
+ percent: totalCandidates > 0 ? Math.min(100, (totalChecked / totalCandidates) * 100) : 0,
189
+ rateKeysPerSec: rate,
190
+ etaSeconds: eta,
191
+ elapsedSeconds: elapsed,
192
+ currentLength,
193
+ currentPosition,
194
+ phase,
195
+ });
196
+ };
197
+ // Helper to verify MAC and filters
198
+ const verifyMacAndFilters = (key) => {
199
+ if (!verifyMac(ciphertext, cipherMac, key)) {
200
+ return { valid: false };
201
+ }
202
+ const result = ChannelCrypto.decryptGroupTextMessage(ciphertext, cipherMac, key);
203
+ if (!result.success || !result.data) {
204
+ return { valid: false };
205
+ }
206
+ if (this.useTimestampFilter && !isTimestampValid(result.data.timestamp, this.validSeconds)) {
207
+ return { valid: false };
208
+ }
209
+ if (this.useUtf8Filter && !isValidUtf8(result.data.message)) {
210
+ return { valid: false };
211
+ }
212
+ return { valid: true, message: result.data.message };
213
+ };
214
+ // Phase 1: Try public key
215
+ if (startFromLength === 1 && startFromOffset === 0) {
216
+ reportProgress('public-key', 0, PUBLIC_ROOM_NAME);
217
+ const publicChannelHash = getChannelHash(PUBLIC_KEY);
218
+ if (channelHash === publicChannelHash) {
219
+ const result = verifyMacAndFilters(PUBLIC_KEY);
220
+ if (result.valid) {
221
+ return {
222
+ found: true,
223
+ roomName: PUBLIC_ROOM_NAME,
224
+ key: PUBLIC_KEY,
225
+ decryptedMessage: result.message,
226
+ };
227
+ }
228
+ }
229
+ }
230
+ // Phase 2: Dictionary attack
231
+ if (useDictionary && this.wordlist.length > 0 && startFromLength === 1 && startFromOffset === 0) {
232
+ for (let i = 0; i < this.wordlist.length; i++) {
233
+ if (this.abortFlag) {
234
+ return {
235
+ found: false,
236
+ aborted: true,
237
+ resumeFrom: this.wordlist[i],
238
+ };
239
+ }
240
+ const word = this.wordlist[i];
241
+ const key = deriveKeyFromRoomName('#' + word);
242
+ const wordChannelHash = getChannelHash(key);
243
+ if (parseInt(wordChannelHash, 16) === targetHashByte) {
244
+ const result = verifyMacAndFilters(key);
245
+ if (result.valid) {
246
+ return {
247
+ found: true,
248
+ roomName: word,
249
+ key,
250
+ decryptedMessage: result.message,
251
+ };
252
+ }
253
+ }
254
+ // Progress update
255
+ const now = performance.now();
256
+ if (now - lastProgressUpdate >= 200) {
257
+ reportProgress('wordlist', word.length, word);
258
+ lastProgressUpdate = now;
259
+ await new Promise((resolve) => setTimeout(resolve, 0));
260
+ }
261
+ }
262
+ }
263
+ // Phase 3: Brute force (GPU or CPU)
264
+ // Use smaller batches for CPU since it's much slower
265
+ const INITIAL_BATCH_SIZE = this.useCpu ? 1024 : 32768;
266
+ const TARGET_DISPATCH_MS = 1000;
267
+ let currentBatchSize = INITIAL_BATCH_SIZE;
268
+ let batchSizeTuned = false;
269
+ for (let length = startFromLength; length <= maxLength; length++) {
270
+ if (this.abortFlag) {
271
+ const resumePos = indexToRoomName(length, 0);
272
+ return {
273
+ found: false,
274
+ aborted: true,
275
+ resumeFrom: resumePos || undefined,
276
+ };
277
+ }
278
+ const totalForLength = countNamesForLength(length);
279
+ let offset = length === startFromLength ? startFromOffset : 0;
280
+ while (offset < totalForLength) {
281
+ if (this.abortFlag) {
282
+ const resumePos = indexToRoomName(length, offset);
283
+ return {
284
+ found: false,
285
+ aborted: true,
286
+ resumeFrom: resumePos || undefined,
287
+ };
288
+ }
289
+ const batchSize = Math.min(currentBatchSize, totalForLength - offset);
290
+ const dispatchStart = performance.now();
291
+ // Run batch on GPU or CPU
292
+ let matches;
293
+ if (this.useCpu) {
294
+ matches = this.cpuInstance.runBatch(targetHashByte, length, offset, batchSize, ciphertext, cipherMac);
295
+ }
296
+ else {
297
+ matches = await this.gpuInstance.runBatch(targetHashByte, length, offset, batchSize, ciphertext, cipherMac);
298
+ }
299
+ const dispatchTime = performance.now() - dispatchStart;
300
+ totalChecked += batchSize;
301
+ // Auto-tune batch size (GPU only)
302
+ if (!this.useCpu && !batchSizeTuned && batchSize >= INITIAL_BATCH_SIZE && dispatchTime > 0) {
303
+ const scaleFactor = TARGET_DISPATCH_MS / dispatchTime;
304
+ const optimalBatchSize = Math.round(batchSize * scaleFactor);
305
+ const rounded = Math.pow(2, Math.round(Math.log2(Math.max(INITIAL_BATCH_SIZE, optimalBatchSize))));
306
+ currentBatchSize = Math.max(INITIAL_BATCH_SIZE, rounded);
307
+ batchSizeTuned = true;
308
+ }
309
+ // Check matches
310
+ for (const matchIdx of matches) {
311
+ const roomName = indexToRoomName(length, matchIdx);
312
+ if (!roomName)
313
+ continue;
314
+ const key = deriveKeyFromRoomName('#' + roomName);
315
+ const result = verifyMacAndFilters(key);
316
+ if (result.valid) {
317
+ return {
318
+ found: true,
319
+ roomName,
320
+ key,
321
+ decryptedMessage: result.message,
322
+ };
323
+ }
324
+ }
325
+ offset += batchSize;
326
+ // Progress update
327
+ const now = performance.now();
328
+ if (now - lastProgressUpdate >= 200) {
329
+ const currentPos = indexToRoomName(length, Math.min(offset, totalForLength - 1)) || '';
330
+ reportProgress('bruteforce', length, currentPos);
331
+ lastProgressUpdate = now;
332
+ await new Promise((resolve) => setTimeout(resolve, 0));
333
+ }
334
+ }
335
+ }
336
+ // Not found
337
+ const lastPos = indexToRoomName(maxLength, countNamesForLength(maxLength) - 1);
338
+ return {
339
+ found: false,
340
+ resumeFrom: lastPos || undefined,
341
+ };
342
+ }
343
+ /**
344
+ * Clean up resources.
345
+ * Call this when you're done using the cracker.
346
+ */
347
+ destroy() {
348
+ if (this.gpuInstance) {
349
+ this.gpuInstance.destroy();
350
+ this.gpuInstance = null;
351
+ }
352
+ if (this.cpuInstance) {
353
+ this.cpuInstance.destroy();
354
+ this.cpuInstance = null;
355
+ }
356
+ }
357
+ }
358
+ //# sourceMappingURL=cracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cracker.js","sourceRoot":"","sources":["../src/cracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export interface GpuBruteForceResult {
2
+ found: boolean;
3
+ roomName?: string;
4
+ key?: string;
5
+ candidateIndices?: number[];
6
+ }
7
+ export declare class GpuBruteForce {
8
+ private device;
9
+ private pipeline;
10
+ private bindGroupLayout;
11
+ private paramsBuffer;
12
+ private matchCountBuffer;
13
+ private matchIndicesBuffer;
14
+ private ciphertextBuffer;
15
+ private ciphertextBufferSize;
16
+ private matchCountReadBuffers;
17
+ private matchIndicesReadBuffers;
18
+ private currentReadBufferIndex;
19
+ private bindGroup;
20
+ private bindGroupDirty;
21
+ private static readonly ZERO_DATA;
22
+ private shaderCode;
23
+ init(): Promise<boolean>;
24
+ isAvailable(): boolean;
25
+ indexToRoomName(idx: number, length: number): string | null;
26
+ countNamesForLength(len: number): number;
27
+ runBatch(targetChannelHash: number, nameLength: number, batchOffset: number, batchSize: number, ciphertextHex?: string, targetMacHex?: string): Promise<number[]>;
28
+ destroy(): void;
29
+ }
30
+ /**
31
+ * Check if WebGPU is supported in the current browser.
32
+ */
33
+ export declare function isWebGpuSupported(): boolean;
34
+ //# sourceMappingURL=gpu-bruteforce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu-bruteforce.d.ts","sourceRoot":"","sources":["../src/gpu-bruteforce.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,eAAe,CAAmC;IAG1D,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,oBAAoB,CAAa;IAGzC,OAAO,CAAC,qBAAqB,CAAsD;IACnF,OAAO,CAAC,uBAAuB,CAAsD;IACrF,OAAO,CAAC,sBAAsB,CAAa;IAG3C,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,cAAc,CAAiB;IAGvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAGzD,OAAO,CAAC,UAAU,CAkYlB;IAEM,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IA8E9B,WAAW,IAAI,OAAO;IAKtB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAK3D,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIlC,QAAQ,CACZ,iBAAiB,EAAE,MAAM,EACzB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,EACtB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC;IAkJpB,OAAO,IAAI,IAAI;CA+BhB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C"}