meshcore-hashtag-cracker 1.3.1 → 1.4.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/README.md +1 -1
- package/browser/meshcore_cracker.min.js +2 -2
- package/browser/meshcore_cracker.min.js.map +2 -2
- package/browser/testbed.html +51 -73
- package/dist/cracker.js +1 -1
- package/dist/cracker.js.map +1 -1
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# MeshCore GroupText Hashtag Room Cracker
|
|
4
4
|
|
|
5
|
-
Standalone library for cracking MeshCore GroupText packets from hashtag rooms using WebGPU-accelerated brute force (with fallbacks for our non-GPU brethren).
|
|
5
|
+
Standalone library for cracking MeshCore GroupText packets from hashtag rooms using WebGPU-accelerated brute force (with fallbacks for our non-GPU brethren and dictionary attack support).
|
|
6
6
|
|
|
7
7
|
**Note:** This tool is designed exclusively for cracking public hashtag rooms (e.g., `#general`, `#test`). It does not support private rooms or other MeshCore encryption schemes (or, rather, it will attempt to crack them, but nearly certainly fail)
|
|
8
8
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* MeshCore Hashtag Room Cracker v1.
|
|
2
|
+
* MeshCore Hashtag Room Cracker v1.4.0
|
|
3
3
|
* https://github.com/jkingsman/meshcore-hashtag-cracker
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) 2026 Jack Kingsman
|
|
@@ -405,7 +405,7 @@ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
407
|
`}async init(){if(!navigator.gpu)return console.warn("WebGPU not supported"),!1;try{let e=await navigator.gpu.requestAdapter();if(!e)return console.warn("No GPU adapter found"),!1;this.device=await e.requestDevice(),this.bindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}]}),this.paramsBuffer=this.device.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.matchCountBuffer=this.device.createBuffer({size:4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST}),this.matchIndicesBuffer=this.device.createBuffer({size:1024*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC});for(let a=0;a<2;a++)this.matchCountReadBuffers[a]=this.device.createBuffer({size:4,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),this.matchIndicesReadBuffers[a]=this.device.createBuffer({size:1024*4,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST});let r=this.device.createShaderModule({code:this.shaderCode}),n=this.device.createPipelineLayout({bindGroupLayouts:[this.bindGroupLayout]});return this.pipeline=this.device.createComputePipeline({layout:n,compute:{module:r,entryPoint:"main"}}),!0}catch(e){return console.error("WebGPU initialization failed:",e),!1}}isAvailable(){return this.device!==null&&this.pipeline!==null}indexToRoomName(e,r){return ve(r,e)}countNamesForLength(e){return Re(e)}async runBatch(e,r,n,a,s,c){if(!this.device||!this.pipeline||!this.bindGroupLayout||!this.paramsBuffer||!this.matchCountBuffer||!this.matchIndicesBuffer||!this.matchCountReadBuffers[0]||!this.matchCountReadBuffers[1]||!this.matchIndicesReadBuffers[0]||!this.matchIndicesReadBuffers[1])throw new Error("GPU not initialized");let i=this.currentReadBufferIndex;this.currentReadBufferIndex=1-this.currentReadBufferIndex;let x=this.matchCountReadBuffers[i],d=this.matchIndicesReadBuffers[i],o=s&&c?1:0,f,u=0,p=0;if(o){let C=new Uint8Array(s.length/2);for(let q=0;q<C.length;q++)C[q]=parseInt(s.substr(q*2,2),16);u=C.length*8;let v=Math.ceil(C.length/4)*4,S=new Uint8Array(v);S.set(C),f=new Uint32Array(v/4);for(let q=0;q<f.length;q++)f[q]=S[q*4]<<24|S[q*4+1]<<16|S[q*4+2]<<8|S[q*4+3];let w=parseInt(c.substr(0,2),16),R=parseInt(c.substr(2,2),16);p=w<<24|R<<16}else f=new Uint32Array([0]);let y=Math.max(f.length*4,4);(!this.ciphertextBuffer||this.ciphertextBufferSize<y)&&(this.ciphertextBuffer&&this.ciphertextBuffer.destroy(),this.ciphertextBuffer=this.device.createBuffer({size:y,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.ciphertextBufferSize=y,this.bindGroupDirty=!0);let g=new Uint32Array([e,n,r,a,p,f.length,u,o]);this.device.queue.writeBuffer(this.paramsBuffer,0,g),this.device.queue.writeBuffer(this.ciphertextBuffer,0,f),this.device.queue.writeBuffer(this.matchCountBuffer,0,br.ZERO_DATA),(this.bindGroupDirty||!this.bindGroup)&&(this.bindGroup=this.device.createBindGroup({layout:this.bindGroupLayout,entries:[{binding:0,resource:{buffer:this.paramsBuffer}},{binding:1,resource:{buffer:this.matchCountBuffer}},{binding:2,resource:{buffer:this.matchIndicesBuffer}},{binding:3,resource:{buffer:this.ciphertextBuffer}}]}),this.bindGroupDirty=!1);let m=this.device.createCommandEncoder(),l=m.beginComputePass();l.setPipeline(this.pipeline),l.setBindGroup(0,this.bindGroup),l.dispatchWorkgroups(Math.ceil(a/(256*16))),l.end(),m.copyBufferToBuffer(this.matchCountBuffer,0,x,0,4),m.copyBufferToBuffer(this.matchIndicesBuffer,0,d,0,1024*4),this.device.queue.submit([m.finish()]),await x.mapAsync(GPUMapMode.READ);let b=new Uint32Array(x.getMappedRange())[0];x.unmap();let B=[];if(b>0){await d.mapAsync(GPUMapMode.READ);let C=new Uint32Array(d.getMappedRange());for(let v=0;v<Math.min(b,1024);v++)B.push(C[v]);d.unmap()}return B}destroy(){this.paramsBuffer?.destroy(),this.matchCountBuffer?.destroy(),this.matchIndicesBuffer?.destroy(),this.ciphertextBuffer?.destroy(),this.matchCountReadBuffers[0]?.destroy(),this.matchCountReadBuffers[1]?.destroy(),this.matchIndicesReadBuffers[0]?.destroy(),this.matchIndicesReadBuffers[1]?.destroy(),this.paramsBuffer=null,this.matchCountBuffer=null,this.matchIndicesBuffer=null,this.ciphertextBuffer=null,this.ciphertextBufferSize=0,this.matchCountReadBuffers=[null,null],this.matchIndicesReadBuffers=[null,null],this.currentReadBufferIndex=0,this.bindGroup=null,this.bindGroupDirty=!0,this.device&&(this.device.destroy(),this.device=null),this.pipeline=null,this.bindGroupLayout=null}};br.ZERO_DATA=new Uint32Array([0]);var Br=br;function Cr(){return typeof navigator<"u"&&"gpu"in navigator}var G0=class{runBatch(e,r,n,a,s,c){let i=[],x=e.toString(16).padStart(2,"0"),d=!!(s&&c);for(let o=0;o<a;o++){let f=n+o,u=ve(r,f);if(!u)continue;let p=i0("#"+u);o0(p)===x&&(d&&!S0(s,c,p)||i.push(f))}return i}destroy(){}};var eo=/^[a-z0-9-]+$/,to=/^[a-z0-9].*[a-z0-9]$|^[a-z0-9]$/,ro=/--/;function Ra(t){return!(!t||t.length===0||!eo.test(t)||t.length>1&&!to.test(t)||ro.test(t))}var Ar=class{constructor(){this.gpuInstance=null;this.cpuInstance=null;this.wordlist=[];this.abortFlag=!1;this.useTimestampFilter=!0;this.useUtf8Filter=!0;this.validSeconds=w0;this.useCpu=!1}async loadWordlist(e){let r=await fetch(e);if(!r.ok)throw new Error(`Failed to load wordlist: ${r.status} ${r.statusText}`);let a=(await r.text()).split(`
|
|
408
|
-
`).map(s=>s.trim().toLowerCase()).filter(s=>s.length>0);this.wordlist=a.filter(Ra)}setWordlist(e){this.wordlist=e.map(r=>r.trim().toLowerCase()).filter(Ra)}abort(){this.abortFlag=!0}isGpuAvailable(){return Cr()}async decodePacket(e){let r=e.trim().replace(/\s+/g,"").replace(/^0x/i,"");if(!r||!/^[0-9a-fA-F]+$/.test(r))return null;try{let a=(await _r.MeshCorePacketDecoder.decodeWithVerification(r,{})).payload?.decoded;return!a?.channelHash||!a?.ciphertext||!a?.cipherMac?null:{channelHash:a.channelHash,ciphertext:a.ciphertext,cipherMac:a.cipherMac,isGroupText:!0}}catch{return null}}async crack(e,r,n){this.abortFlag=!1,this.useTimestampFilter=r?.useTimestampFilter??!0,this.useUtf8Filter=r?.useUtf8Filter??!0,this.validSeconds=r?.validSeconds??w0,this.useCpu=r?.forceCpu??!1;let a=r?.maxLength??8,s=r?.startingLength??1,c=r?.useDictionary??!0,i=r?.startFromType??"bruteforce",x=e.toLowerCase(),d=await this.decodePacket(x);if(!d)return{found:!1,error:"Invalid packet or not a GroupText packet"};let{channelHash:o,ciphertext:f,cipherMac:u}=d,p=parseInt(o,16);this.useCpu?this.cpuInstance||(this.cpuInstance=new G0):this.gpuInstance||(this.gpuInstance=new Br,await this.gpuInstance.init()||(this.useCpu=!0,this.cpuInstance=new G0));let y=performance.now(),g=0,m=performance.now(),l=s,h=0,b=0,B=!1;if(r?.startFrom){let T=r.startFrom.toLowerCase();if(i==="dictionary"){let A=this.wordlist.indexOf(T);A>=0&&(b=A+1)}else{B=!0;let A=vr(T);A&&(l=Math.max(s,A.length),h=A.index+1,h>=Re(l)&&(l++,h=0))}}let C=0;c&&!B&&this.wordlist.length>0&&(C+=this.wordlist.length-b);for(let T=l;T<=a;T++)C+=Re(T);C-=h;let v=(T,A,N)=>{if(!n)return;let L=(performance.now()-y)/1e3,K=L>0?Math.round(g/L):0,F=C-g,P=K>0?F/K:0;n({checked:g,total:C,percent:C>0?Math.min(100,g/C*100):0,rateKeysPerSec:K,etaSeconds:P,elapsedSeconds:L,currentLength:A,currentPosition:N,phase:T})},S=T=>{if(!S0(f,u,T))return{valid:!1};let A=_r.ChannelCrypto.decryptGroupTextMessage(f,u,T);return!A.success||!A.data?{valid:!1}:this.useTimestampFilter&&!gr(A.data.timestamp,this.validSeconds)?{valid:!1}:this.useUtf8Filter&&!mr(A.data.message)?{valid:!1}:{valid:!0,message:A.data.message}};if(!B&&b===0&&l===s&&h===0){v("public-key",0,F0);let T=o0(a0);if(o===T){let A=S(a0);if(A.valid)return{found:!0,roomName:F0,key:a0,decryptedMessage:A.message}}}if(c&&!B&&this.wordlist.length>0)for(let T=b;T<this.wordlist.length;T++){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:this.wordlist[T],resumeType:"dictionary"};let A=this.wordlist[T],N=i0("#"+A),O=o0(N);if(parseInt(O,16)===p){let K=S(N);if(K.valid)return{found:!0,roomName:A,key:N,decryptedMessage:K.message,resumeFrom:A,resumeType:"dictionary"}}g++;let L=performance.now();L-m>=200&&(v("wordlist",A.length,A),m=L,await new Promise(K=>setTimeout(K,0)))}let w=this.useCpu?1024:32768,R=1e3,q=w,_=!1;for(let T=l;T<=a;T++){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:ve(T,0)||void 0,resumeType:"bruteforce"};let A=Re(T),N=T===l?h:0;for(;N<A;){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:ve(T,N)||void 0,resumeType:"bruteforce"};let O=Math.min(q,A-N),L=performance.now(),K;this.useCpu?K=this.cpuInstance.runBatch(p,T,N,O,f,u):K=await this.gpuInstance.runBatch(p,T,N,O,f,u);let F=performance.now()-L;if(g+=O,!this.useCpu&&!_&&O>=w&&F>0){let k=R/F,E=Math.round(O*k),W=Math.pow(2,Math.round(Math.log2(Math.max(w,E))));q=Math.max(w,W),_=!0}for(let k of K){let E=ve(T,k);if(!E)continue;let W=i0("#"+E),J=S(W);if(J.valid)return{found:!0,roomName:E,key:W,decryptedMessage:J.message,resumeFrom:E,resumeType:"bruteforce"}}N+=O;let P=performance.now();if(P-m>=200){let k=ve(T,Math.min(N,A-1))||"";v("bruteforce",T,k),m=P,await new Promise(E=>setTimeout(E,0))}}}return{found:!1,resumeFrom:ve(a,Re(a)-1)||void 0,resumeType:"bruteforce"}}destroy(){this.gpuInstance&&(this.gpuInstance.destroy(),this.gpuInstance=null),this.cpuInstance&&(this.cpuInstance.destroy(),this.cpuInstance=null)}};return Cn(no);})();
|
|
408
|
+
`).map(s=>s.trim().toLowerCase()).filter(s=>s.length>0);this.wordlist=a.filter(Ra)}setWordlist(e){this.wordlist=e.map(r=>r.trim().toLowerCase()).filter(Ra)}abort(){this.abortFlag=!0}isGpuAvailable(){return Cr()}async decodePacket(e){let r=e.trim().replace(/\s+/g,"").replace(/^0x/i,"");if(!r||!/^[0-9a-fA-F]+$/.test(r))return null;try{let a=(await _r.MeshCorePacketDecoder.decodeWithVerification(r,{})).payload?.decoded;return!a?.channelHash||!a?.ciphertext||!a?.cipherMac?null:{channelHash:a.channelHash,ciphertext:a.ciphertext,cipherMac:a.cipherMac,isGroupText:!0}}catch{return null}}async crack(e,r,n){this.abortFlag=!1,this.useTimestampFilter=r?.useTimestampFilter??!0,this.useUtf8Filter=r?.useUtf8Filter??!0,this.validSeconds=r?.validSeconds??w0,this.useCpu=r?.forceCpu??!1;let a=r?.maxLength??8,s=r?.startingLength??1,c=r?.useDictionary??!0,i=r?.startFromType??"bruteforce",x=e.toLowerCase(),d=await this.decodePacket(x);if(!d)return{found:!1,error:"Invalid packet or not a GroupText packet"};let{channelHash:o,ciphertext:f,cipherMac:u}=d,p=parseInt(o,16);this.useCpu?this.cpuInstance||(this.cpuInstance=new G0):this.gpuInstance||(this.gpuInstance=new Br,await this.gpuInstance.init()||(this.useCpu=!0,this.cpuInstance=new G0));let y=performance.now(),g=0,m=performance.now(),l=s,h=0,b=0,B=!1;if(r?.startFrom){let T=r.startFrom.toLowerCase();if(i==="dictionary"){let A=this.wordlist.indexOf(T);A>=0&&(b=A+1)}else{B=!0;let A=vr(T);A&&(l=Math.max(s,A.length),h=A.index+1,h>=Re(l)&&(l++,h=0))}}let C=0;c&&!B&&this.wordlist.length>0&&(C+=this.wordlist.length-b);for(let T=l;T<=a;T++)C+=Re(T);C-=h;let v=(T,A,N)=>{if(!n)return;let L=(performance.now()-y)/1e3,K=L>0?Math.round(g/L):0,F=C-g,P=K>0?F/K:0;n({checked:g,total:C,percent:C>0?Math.min(100,g/C*100):0,rateKeysPerSec:K,etaSeconds:P,elapsedSeconds:L,currentLength:A,currentPosition:N,phase:T})},S=T=>{if(!S0(f,u,T))return{valid:!1};let A=_r.ChannelCrypto.decryptGroupTextMessage(f,u,T);return!A.success||!A.data?{valid:!1}:this.useTimestampFilter&&!gr(A.data.timestamp,this.validSeconds)?{valid:!1}:this.useUtf8Filter&&!mr(A.data.message)?{valid:!1}:{valid:!0,message:A.data.message}};if(!B&&b===0&&l===s&&h===0){v("public-key",0,F0);let T=o0(a0);if(o===T){let A=S(a0);if(A.valid)return{found:!0,roomName:F0,key:a0,decryptedMessage:A.message}}}if(c&&!B&&this.wordlist.length>0)for(let T=b;T<this.wordlist.length;T++){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:this.wordlist[T],resumeType:"dictionary"};let A=this.wordlist[T],N=i0("#"+A),O=o0(N);if(parseInt(O,16)===p){let K=S(N);if(K.valid)return{found:!0,roomName:A,key:N,decryptedMessage:K.message,resumeFrom:A,resumeType:"dictionary"}}g++;let L=performance.now();L-m>=200&&(v("wordlist",A.length,A),m=L,await new Promise(K=>setTimeout(K,0)))}let w=this.useCpu?1024:32768,R=r?.gpuDispatchMs??1e3,q=w,_=!1;for(let T=l;T<=a;T++){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:ve(T,0)||void 0,resumeType:"bruteforce"};let A=Re(T),N=T===l?h:0;for(;N<A;){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:ve(T,N)||void 0,resumeType:"bruteforce"};let O=Math.min(q,A-N),L=performance.now(),K;this.useCpu?K=this.cpuInstance.runBatch(p,T,N,O,f,u):K=await this.gpuInstance.runBatch(p,T,N,O,f,u);let F=performance.now()-L;if(g+=O,!this.useCpu&&!_&&O>=w&&F>0){let k=R/F,E=Math.round(O*k),W=Math.pow(2,Math.round(Math.log2(Math.max(w,E))));q=Math.max(w,W),_=!0}for(let k of K){let E=ve(T,k);if(!E)continue;let W=i0("#"+E),J=S(W);if(J.valid)return{found:!0,roomName:E,key:W,decryptedMessage:J.message,resumeFrom:E,resumeType:"bruteforce"}}N+=O;let P=performance.now();if(P-m>=200){let k=ve(T,Math.min(N,A-1))||"";v("bruteforce",T,k),m=P,await new Promise(E=>setTimeout(E,0))}}}return{found:!1,resumeFrom:ve(a,Re(a)-1)||void 0,resumeType:"bruteforce"}}destroy(){this.gpuInstance&&(this.gpuInstance.destroy(),this.gpuInstance=null),this.cpuInstance&&(this.cpuInstance.destroy(),this.cpuInstance=null)}};return Cn(no);})();
|
|
409
409
|
/*! Bundled license information:
|
|
410
410
|
|
|
411
411
|
crypto-js/ripemd160.js:
|