Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
458 changes: 392 additions & 66 deletions frontend/src/App.tsx

Large diffs are not rendered by default.

154 changes: 115 additions & 39 deletions frontend/src/hash.worker.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,37 @@
import init, { Sha256Hasher, Sha512Hasher, Md5Hasher, Blake3Hasher } from './pkg/hash_wasm';
import init, {
Sha1Hasher,
Sha256Hasher,
Sha512Hasher,
Md5Hasher,
Blake3Hasher,
Sha224Hasher,
Sha384Hasher,
Sha512_224Hasher,
Sha512_256Hasher,
Sha3_224Hasher,
Sha3_256Hasher,
Sha3_384Hasher,
Sha3_512Hasher,
Shake128Hasher,
Shake256Hasher,
Blake2sHasher,
Blake2bHasher,
Ripemd160Hasher,
Md4Hasher,
Md2Hasher,
WhirlpoolHasher,
Sm3Hasher,
Crc32Hasher,
Adler32Hasher,
Fnv1Hasher,
Fnv1aHasher,
Murmur3Hasher,
XxHashHasher,
SipHashHasher,
LuhnHasher,
VerhoeffHasher,
DammHasher
} from './pkg/hash_wasm';

let wasmInitialized = false;

Expand All @@ -15,51 +48,94 @@ function toHex(bytes: Uint8Array): string {
.join('');
}

// Map algorithm key to its Hasher class construction
const hashersConfig = {
sha1: Sha1Hasher,
sha256: Sha256Hasher,
sha512: Sha512Hasher,
md5: Md5Hasher,
blake3: Blake3Hasher,
sha224: Sha224Hasher,
sha384: Sha384Hasher,
sha512_224: Sha512_224Hasher,
sha512_256: Sha512_256Hasher,
sha3_224: Sha3_224Hasher,
sha3_256: Sha3_256Hasher,
sha3_384: Sha3_384Hasher,
sha3_512: Sha3_512Hasher,
shake128: Shake128Hasher,
shake256: Shake256Hasher,
blake2s: Blake2sHasher,
blake2b: Blake2bHasher,
ripemd160: Ripemd160Hasher,
md4: Md4Hasher,
md2: Md2Hasher,
whirlpool: WhirlpoolHasher,
sm3: Sm3Hasher,
crc32: Crc32Hasher,
adler32: Adler32Hasher,
fnv1: Fnv1Hasher,
fnv1a: Fnv1aHasher,
murmur3: Murmur3Hasher,
xxhash: XxHashHasher,
siphash: SipHashHasher,
luhn: LuhnHasher,
verhoeff: VerhoeffHasher,
damm: DammHasher
};

type AlgoKey = keyof typeof hashersConfig;

// Handler for messages from main thread
self.onmessage = async (event: MessageEvent) => {
const { type, data, id } = event.data;

try {
await ensureWasm();

const algoKeys = Object.keys(hashersConfig) as AlgoKey[];

if (type === 'HASH_TEXT') {
const encoder = new TextEncoder();
const bytes = encoder.encode(data || '');

// Perform fast full hashing
const sha256Hasher = new Sha256Hasher();
const sha512Hasher = new Sha512Hasher();
const md5Hasher = new Md5Hasher();
const blake3Hasher = new Blake3Hasher();
// Instantiate all hashers
const instances = {} as Record<AlgoKey, any>;
for (const k of algoKeys) {
instances[k] = new hashersConfig[k]();
}

sha256Hasher.update(bytes);
sha512Hasher.update(bytes);
md5Hasher.update(bytes);
blake3Hasher.update(bytes);
// Update all hashers
for (const k of algoKeys) {
instances[k].update(bytes);
}

const hash256 = toHex(sha256Hasher.finalize());
const hash512 = toHex(sha512Hasher.finalize());
const hashMd5 = toHex(md5Hasher.finalize());
const hashBlake3 = toHex(blake3Hasher.finalize());
// Finalize all hashes
const results = {} as Record<string, string>;
for (const k of algoKeys) {
const outBytes = instances[k].finalize();
// Since Luhn/Verhoeff/Damm return simple decimals, keep single digit or small array representation
if (k === 'luhn' || k === 'verhoeff' || k === 'damm') {
results[k] = String(outBytes[0]);
} else {
results[k] = toHex(new Uint8Array(outBytes));
}
}

self.postMessage({
type: 'HASH_SUCCESS',
id,
results: {
sha256: hash256,
sha512: hash512,
md5: hashMd5,
blake3: hashBlake3,
}
results
});
} else if (type === 'HASH_FILE') {
const file: File | Blob = data;
const totalSize = file.size;

const sha256Hasher = new Sha256Hasher();
const sha512Hasher = new Sha512Hasher();
const md5Hasher = new Md5Hasher();
const blake3Hasher = new Blake3Hasher();
// Instantiate all hashers
const instances = {} as Record<AlgoKey, any>;
for (const k of algoKeys) {
instances[k] = new hashersConfig[k]();
}
Comment on lines +134 to +138

const CHUNK_SIZE = 4 * 1024 * 1024; // 4MB chunks
let offset = 0;
Expand All @@ -69,10 +145,10 @@ self.onmessage = async (event: MessageEvent) => {
const arrayBuffer = await slice.arrayBuffer();
const chunkBytes = new Uint8Array(arrayBuffer);

sha256Hasher.update(chunkBytes);
sha512Hasher.update(chunkBytes);
md5Hasher.update(chunkBytes);
blake3Hasher.update(chunkBytes);
// Update all hashers
for (const k of algoKeys) {
instances[k].update(chunkBytes);
}

offset += chunkBytes.length;

Expand All @@ -87,21 +163,21 @@ self.onmessage = async (event: MessageEvent) => {
});
}

// Finalize hashes
const hash256 = toHex(sha256Hasher.finalize());
const hash512 = toHex(sha512Hasher.finalize());
const hashMd5 = toHex(md5Hasher.finalize());
const hashBlake3 = toHex(blake3Hasher.finalize());
// Finalize all hashes
const results = {} as Record<string, string>;
for (const k of algoKeys) {
const outBytes = instances[k].finalize();
if (k === 'luhn' || k === 'verhoeff' || k === 'damm') {
results[k] = String(outBytes[0]);
} else {
results[k] = toHex(new Uint8Array(outBytes));
}
}

self.postMessage({
type: 'HASH_SUCCESS',
id,
results: {
sha256: hash256,
sha512: hash512,
md5: hashMd5,
blake3: hashBlake3,
}
results
});
}
} catch (error: any) {
Expand Down
Loading