Build1 distinct publisher3 min readUpdated
A dev.to build log shows where browser-native hashing stops: pull a library for MD5, or hand-roll 100 lines of bit twiddling and own the padding bugs yourself.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A developer published a build log for a browser-only hash calculator after a file upload failed silently and turned out to have been corrupted in transit with nothing catching it [1]. The tool itself is unremarkable, but the decision buried in it is one that every operator verifying files against an older system runs into: the browser's built-in hashing covers four algorithms and pointedly excludes the fifth one the legacy box is asking for [3][5].
`crypto.subtle.digest()` handles SHA-1, SHA-256, SHA-384 and SHA-512 natively, with no dependency and no network round trip [3]. The author's stated reason for building locally was that no hash tool was installed and uploading sensitive files to an unknown web service felt wrong [2], and the finished tool runs entirely client-side [11]. MD5 is absent by design, because MD5 is cryptographically broken [5]. Defensible as policy, and no help at all when the checksum column in an old database is MD5, or when the counterparty's published checksum is MD5 [6].
That leaves two roads: a library such as crypto-js, or an implementation from scratch [7]. The author's charge sheet against the library is extra HTTP requests, supply chain risk, bundle size, and fighting module systems [8]. The case for hand-rolling is that the algorithm is specified in RFC 1321 and comes to roughly 100 lines of bit manipulation [9].
The bill does not arrive in those 100 lines. It arrives at the file boundary. Reading a whole file into memory is fine until a 2GB video crashes the browser, so the tool reads in 1MB chunks [10][12]. The author writes that the SHA path is handled by crypto.subtle's incremental interface [13]; verify that against your own target, because the only digest call shown in the post is a one-shot over a single buffer [4]. For MD5 there was no such option, and streaming state had to be maintained by hand between chunks [14].
Which is exactly where it broke. The first version mishandled padding when the final chunk was not a full 512-bit block [15]. The corrective prompt was specific: when file size is an exact multiple of 64 bytes the padding needs an extra block, and the appended length is in bits, not bytes [16]. Those are the same boundary described twice, since 64 bytes is 512 bits [21]. At a 1MB chunk size that is 16,384 blocks per chunk, and the logic only goes wrong on the last one [22], which is why the initial MD5 body passed known test vectors while the file path did not [18]. Two iterations to fix, and the author's own conclusion is that spotting it required understanding the algorithm first [17].
The small parts are the ones worth copying. Input hashing is debounced at 150ms, capping recomputation at about seven passes per second instead of one per keystroke [19][23]. Hash comparison is case-insensitive with a MATCH or NO MATCH indicator, on the reasonable assumption that nobody reads 64 hex characters correctly by eye [20].
Worth watching: whether your verification target actually requires MD5, because if it will accept SHA-256 the fork disappears and you keep the zero-dependency path. If it will not, test the hand-rolled route at empty input, exactly 64 bytes, and every multiple of 64 near a chunk edge before trusting a green MATCH. This is one developer's account of one tool, with no benchmarks published [24].
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The finished tool runs entirely client-side with no network requests and no dependencies, inside the browser sandbox.
The author debugged a silently failing file upload and found the file had been corrupted during transfer with nothing catching it, prompting a need to verify file integrity by comparing hashes.
The author did not have a hash tool installed and considered uploading sensitive files to random online services wrong, so decided to build the tool.
Modern browsers expose crypto.subtle.digest(), which handles SHA-1, SHA-256, SHA-384 and SHA-512 natively; the author describes it as fast, secure and requiring zero dependencies.
The digest example given in the post is a single one-shot call over one buffer: const hashBuffer = await crypto.subtle.digest('SHA-256', data);
MD5 is not supported by crypto.subtle.digest(); the Web Crypto API deliberately excludes it because MD5 is cryptographically broken.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Code-level detail, single self-reported source
The verifiable core is strong in kind but narrow in breadth: the post shows real snippets for the digest call, the 1MB chunk loop, the debounce and the hash comparison, and names RFC 1321. Everything beyond those snippets is one author's recollection — no MD5 source listing, no test vectors, no benchmarks, and no second publisher. One asserted capability (an incremental crypto.subtle interface) is contradicted by the only Web Crypto usage the post actually demonstrates.
No usage signal
The only adoption-adjacent event is the author announcing and linking his own tool. There are no users, downloads, stars, deployments, dependents or third-party mentions in the supplied source, so adoption cannot be scored without inventing facts.
Modestly overstated capability and performance
The framing is mostly proportionate for a build log, but two threads run ahead of the evidence: the claim that crypto.subtle handles chunked hashing 'elegantly with its incremental interface' is not demonstrated anywhere in the post, which only shows a one-shot digest over one buffer, and the performance assertions (2GB crash, sub-second SHA-512) are anecdotal with no environment or measurement. The ~100-line MD5 figure is also unverifiable since only a stub is shown. Offsetting this, the post is candid about the AI-generated padding bug and about needing human algorithm knowledge, which keeps the gap small rather than large.
Author promotes own hosted tool
The post is written by the tool's builder and closes with a call to try the hosted Hash Calculator, so the narrative that a dependency-free client-side tool is the right answer directly serves the author's own artifact. The security-relevant selling point — no data leaves the browser — is self-asserted rather than audited. There is no disclosed commercial sponsor, paywall or vendor relationship, which keeps this in promotional-self-interest rather than paid-placement territory.
Confident on mechanics, weak on generalisation
Confidence is reasonable for the narrow mechanical claims that appear as code — the API surface, the 1MB chunking, the 150ms debounce, the case-insensitive compare, and the shape of the MD5 padding bug. It falls away for anything requiring corroboration: performance thresholds, correctness of the generated MD5, the shipped tool's network behaviour, and any adoption read. One publisher, one author, zero measurements caps the ceiling.
build
A cached COPY --from=builder shipped yesterday's artifact under today's tag1 distinct publisher
build
Force the tool call, then hand Lightsail a long-lived key1 distinct publisher
build
AI-written code fails the same four ways, and every gate you own reports green1 distinct publisher
build
CSA's 2026 threat list is a flat line, so ask which threats a config snapshot can prove1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 12, 2026