<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bracketly</title>
    <description>The latest articles on DEV Community by Bracketly (@ethan_5b3022150e2c07a4030).</description>
    <link>https://dev.to/ethan_5b3022150e2c07a4030</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4033478%2F8e37796d-86e3-4623-91c8-7d484dca518a.png</url>
      <title>DEV Community: Bracketly</title>
      <link>https://dev.to/ethan_5b3022150e2c07a4030</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ethan_5b3022150e2c07a4030"/>
    <language>en</language>
    <item>
      <title>I Finally Gave Bracketly a Logo That Means Something</title>
      <dc:creator>Bracketly</dc:creator>
      <pubDate>Mon, 20 Jul 2026 12:05:30 +0000</pubDate>
      <link>https://dev.to/ethan_5b3022150e2c07a4030/i-finally-gave-bracketly-a-logo-that-means-something-4np3</link>
      <guid>https://dev.to/ethan_5b3022150e2c07a4030/i-finally-gave-bracketly-a-logo-that-means-something-4np3</guid>
      <description>&lt;h1&gt;
  
  
  I Finally Gave Bracketly a Logo That Means Something
&lt;/h1&gt;

&lt;p&gt;Bracketly has had a favicon since day one — a vaguely hood-shaped abstract mark that, looking back, had nothing to do with the name. It just sat there in the browser tab looking like a placeholder nobody replaced. Today I replaced it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The new mark
&lt;/h2&gt;

&lt;p&gt;It's just &lt;code&gt;[ ]&lt;/code&gt; — two brackets, rendered as rounded stroke paths rather than sharp geometric corners, to match the soft-radius design language already used everywhere else on the site (cards, buttons, pills). Literal, obvious in hindsight, and the kind of thing that should've been there from the start for a site called &lt;em&gt;Bracketly&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It ships in two forms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A monochrome version for the favicon — theme-aware, so it switches between black and white depending on whether your OS is in light or dark mode, same as the rest of the site already does for text and backgrounds.&lt;/li&gt;
&lt;li&gt;A full-color version using the site's existing accent gradient (blue → purple → pink) for the header and anywhere else a full-color mark makes sense.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How it's built
&lt;/h2&gt;

&lt;p&gt;Nothing fancier than two &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; elements with &lt;code&gt;stroke-linecap="round"&lt;/code&gt; and &lt;code&gt;stroke-linejoin="round"&lt;/code&gt; — the rounded bracket ends come for free from the stroke rendering, no manual arc math needed. The tricky part wasn't the shape, it was the spacing: my first attempt had the two brackets' arms overlapping in the middle, which at a glance just looked like a solid rounded rectangle instead of two distinct brackets. Rendered a preview at actual favicon size (32×32) before shipping anything, since a mark that reads fine at 512px can easily turn into mush at the size it actually gets used.&lt;/p&gt;

&lt;p&gt;All the PNG variants (32×32, 512×512, and a 180×180 Apple touch icon for anyone who adds the site to their home screen) are rasterized directly from that one SVG source rather than hand-exported, so there's exactly one file to ever update if the mark changes again.&lt;/p&gt;

&lt;p&gt;Small change, but it's the kind of detail that either quietly signals "someone's paying attention here" or quietly signals the opposite. &lt;a href="https://bracketly.pages.dev/" rel="noopener noreferrer"&gt;Come take a look&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Built a Cron Expression Parser Because I Kept Getting the "Day" Fields Wrong</title>
      <dc:creator>Bracketly</dc:creator>
      <pubDate>Mon, 20 Jul 2026 11:34:37 +0000</pubDate>
      <link>https://dev.to/ethan_5b3022150e2c07a4030/i-built-a-cron-expression-parser-because-i-kept-getting-the-day-fields-wrong-14d0</link>
      <guid>https://dev.to/ethan_5b3022150e2c07a4030/i-built-a-cron-expression-parser-because-i-kept-getting-the-day-fields-wrong-14d0</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Cron Expression Parser Because I Kept Getting the "Day" Fields Wrong
&lt;/h1&gt;

&lt;p&gt;Cron syntax has five fields — minute, hour, day-of-month, month, day-of-week — and most people can read the first three just fine. &lt;code&gt;0 9 * * *&lt;/code&gt; is obviously "9am, every day." It's the interaction between the last two fields that trips people up, and it tripped me up enough times that I added a &lt;a href="https://bracketly.pages.dev/tools/cron-parser/" rel="noopener noreferrer"&gt;Cron Expression Parser&lt;/a&gt; to Bracketly, my free client-side dev tools site.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gotcha: it's OR, not AND
&lt;/h2&gt;

&lt;p&gt;Here's the thing that isn't obvious from staring at &lt;code&gt;0 0 1 * 1&lt;/code&gt;: if you read it left to right, you might assume it means "midnight, on the 1st of the month, AND on a Monday" — i.e. only fires when the 1st happens to land on a Monday.&lt;/p&gt;

&lt;p&gt;That's wrong. Standard cron semantics say: when &lt;em&gt;both&lt;/em&gt; day-of-month and day-of-week are restricted (neither is a bare &lt;code&gt;*&lt;/code&gt;), a date matches if it satisfies &lt;em&gt;either&lt;/em&gt; one. So &lt;code&gt;0 0 1 * 1&lt;/code&gt; actually fires at midnight on the 1st of every month, &lt;em&gt;and separately&lt;/em&gt; every Monday. If you wanted "only when the 1st is a Monday," cron can't directly express that at all.&lt;/p&gt;

&lt;p&gt;This isn't a bug anywhere — it's just how POSIX cron has always worked — but it's exactly the kind of thing you forget between the few times a year you write a cron expression, and get wrong silently until a job fires on a day you didn't expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the tool does
&lt;/h2&gt;

&lt;p&gt;Paste a cron expression (or one of the &lt;code&gt;@daily&lt;/code&gt; / &lt;code&gt;@hourly&lt;/code&gt; / &lt;code&gt;@weekly&lt;/code&gt; shortcuts) and it gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A plain-English explanation, written to make the OR-not-AND behavior explicit rather than paper over it&lt;/li&gt;
&lt;li&gt;The next 5 times the schedule will actually fire, computed from your current time&lt;/li&gt;
&lt;li&gt;Inline validation — a field like &lt;code&gt;99 * * * *&lt;/code&gt; gets a specific "value out of range" error instead of just silently doing something unexpected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like every tool on Bracketly, it's 100% client-side — the parsing and date math happen in your browser, nothing is sent anywhere. It supports the standard field syntax (&lt;code&gt;*&lt;/code&gt;, ranges like &lt;code&gt;1-5&lt;/code&gt;, steps like &lt;code&gt;*/15&lt;/code&gt;, comma lists like &lt;code&gt;1,15&lt;/code&gt;), though numeric fields only for now — no &lt;code&gt;MON&lt;/code&gt;/&lt;code&gt;JAN&lt;/code&gt;-style names yet.&lt;/p&gt;

&lt;p&gt;If you've ever second-guessed whether your deploy schedule actually means what you think it means, it's free and takes about ten seconds to check: &lt;a href="https://bracketly.pages.dev/tools/cron-parser/" rel="noopener noreferrer"&gt;bracketly.pages.dev/tools/cron-parser&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Cloudflare's "Autoconfig" Bot Quietly Broke My Static Site's Deploy — Here's What Happened</title>
      <dc:creator>Bracketly</dc:creator>
      <pubDate>Mon, 20 Jul 2026 06:08:39 +0000</pubDate>
      <link>https://dev.to/ethan_5b3022150e2c07a4030/cloudflares-autoconfig-bot-quietly-broke-my-static-sites-deploy-heres-what-happened-28e1</link>
      <guid>https://dev.to/ethan_5b3022150e2c07a4030/cloudflares-autoconfig-bot-quietly-broke-my-static-sites-deploy-heres-what-happened-28e1</guid>
      <description>&lt;h1&gt;
  
  
  Cloudflare's "Autoconfig" Bot Quietly Broke My Static Site's Deploy — Here's What Happened
&lt;/h1&gt;

&lt;p&gt;A few days ago, Cloudflare's &lt;code&gt;cloudflare-workers-and-pages[bot]&lt;/code&gt; opened a pull request on &lt;a href="https://bracketly.pages.dev" rel="noopener noreferrer"&gt;Bracketly&lt;/a&gt;'s repo, titled "Add Cloudflare Workers configuration." It sat there unmerged while I worked on other things. Today I merged it without thinking too hard about it — it's from Cloudflare's own bot, on a project already hosted on Cloudflare Pages, seemed safe enough.&lt;/p&gt;

&lt;p&gt;It took the site down.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the PR actually did
&lt;/h2&gt;

&lt;p&gt;It added the &lt;code&gt;@astrojs/cloudflare&lt;/code&gt; adapter to &lt;code&gt;astro.config.mjs&lt;/code&gt;, generated a &lt;code&gt;wrangler.jsonc&lt;/code&gt;, and updated &lt;code&gt;package.json&lt;/code&gt;. The framing in the PR description is "configures your project for Cloudflare Workers deployment," which sounds like a reasonable modernization — Workers is Cloudflare's newer, more capable runtime.&lt;/p&gt;

&lt;p&gt;The problem: Bracketly is a 100% static, client-side site. Every "tool" on it (JSON formatter, Base64 encoder, hash generator, etc.) runs entirely in the browser — there was never a server-rendering need to justify a Workers adapter in the first place.&lt;/p&gt;

&lt;p&gt;Adding the adapter restructured the build output. Before: a flat &lt;code&gt;dist/&lt;/code&gt; with &lt;code&gt;index.html&lt;/code&gt; at the root, exactly what a plain static-file deploy expects. After: &lt;code&gt;dist/client/&lt;/code&gt; (the actual site) and &lt;code&gt;dist/server/&lt;/code&gt; (a Workers runtime bundle), because the adapter assumes you want on-demand server rendering alongside static assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it "succeeded" while actually being broken
&lt;/h2&gt;

&lt;p&gt;My existing GitHub Actions deploy step ran &lt;code&gt;wrangler pages deploy dist&lt;/code&gt; — the same command that had worked for weeks. It reported success. The build succeeded. The deploy step reported "Deployment complete." Every automated signal said everything was fine.&lt;/p&gt;

&lt;p&gt;Wrangler had actually detected the new &lt;code&gt;dist/client/wrangler.json&lt;/code&gt; and silently redirected the deploy target from &lt;code&gt;dist&lt;/code&gt; to &lt;code&gt;dist/client&lt;/code&gt; on its own — a "helpful" auto-detection feature that meant the command exit code was misleading. It genuinely uploaded files and genuinely returned success. It just wasn't obviously communicating that the actual site paths (&lt;code&gt;/&lt;/code&gt;, &lt;code&gt;/tools/whatever&lt;/code&gt;, the sitemap) were now 404ing.&lt;/p&gt;

&lt;p&gt;I only caught it because I happened to run a manual &lt;code&gt;curl&lt;/code&gt; against the live homepage right after the merge and got nothing back where a title tag should be.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git revert -m 1 &amp;lt;merge-commit&amp;gt;&lt;/code&gt;, rebuild locally to confirm &lt;code&gt;dist/index.html&lt;/code&gt; exists again (not nested), push. Total downtime: a few minutes, only because I was actively watching for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual lesson
&lt;/h2&gt;

&lt;p&gt;Automated "helpful" configuration bots — especially ones with commit/PR access to your deploy pipeline — don't know your project's actual architecture. This one assumed "Cloudflare Pages project" implies "wants Workers/SSR," which is a reasonable &lt;em&gt;default&lt;/em&gt; guess but was flatly wrong for a purely static site. A green checkmark on a CI deploy step is not the same thing as "the site actually works" — it just means the command didn't throw a non-zero exit code. Worth an actual &lt;code&gt;curl&lt;/code&gt; against production after any deploy-pipeline change, automated or not, regardless of how official-looking the bot that proposed it is.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Silent Cloudflare Pages Bug That Was Quietly Hurting My SEO</title>
      <dc:creator>Bracketly</dc:creator>
      <pubDate>Mon, 20 Jul 2026 05:55:33 +0000</pubDate>
      <link>https://dev.to/ethan_5b3022150e2c07a4030/the-silent-cloudflare-pages-bug-that-was-quietly-hurting-my-seo-3oi7</link>
      <guid>https://dev.to/ethan_5b3022150e2c07a4030/the-silent-cloudflare-pages-bug-that-was-quietly-hurting-my-seo-3oi7</guid>
      <description>&lt;h1&gt;
  
  
  The Silent Cloudflare Pages Bug That Was Quietly Hurting My SEO
&lt;/h1&gt;

&lt;p&gt;While building a broken-link checker for &lt;a href="https://bracketly.pages.dev" rel="noopener noreferrer"&gt;Bracketly&lt;/a&gt; (a small free dev-tools site), I found something I wasn't expecting: every nonexistent URL on the site — &lt;code&gt;/literally-anything-i-typed&lt;/code&gt;, &lt;code&gt;/tools/does-not-exist&lt;/code&gt;, whatever — was returning &lt;strong&gt;HTTP 200&lt;/strong&gt;, with the homepage's content, instead of a 404.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this happens
&lt;/h2&gt;

&lt;p&gt;Cloudflare Pages has a fallback behavior for unmatched routes: if your deployed site has no &lt;code&gt;404.html&lt;/code&gt;, it serves &lt;code&gt;index.html&lt;/code&gt; for any path it can't otherwise resolve — but critically, it does this with a &lt;strong&gt;200 status code&lt;/strong&gt;, not 404. This is the classic SPA-router pattern (makes sense for a client-side-routed React/Vue app where you &lt;em&gt;want&lt;/em&gt; every path to load &lt;code&gt;index.html&lt;/code&gt; and let JS take over routing). It's the wrong default for a plain static multi-page site, and if you never explicitly add a &lt;code&gt;404.html&lt;/code&gt;, you get it silently, with zero warning.&lt;/p&gt;

&lt;p&gt;I only noticed because I was building a script to curl every URL in my sitemap and flag non-200 responses — and a deliberately-broken test URL came back green.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it's worse than it looks
&lt;/h2&gt;

&lt;p&gt;This is what's sometimes called a "soft 404" — a page that &lt;em&gt;should&lt;/em&gt; be an error but returns success. Search engines treat this specially, and not kindly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google's crawler explicitly detects soft-404 patterns (repeated identical content served at different URLs with a 200 status) and can flag the pattern site-wide, not just the one URL&lt;/li&gt;
&lt;li&gt;Every broken/mistyped/old link pointing at your site becomes a duplicate-content page in Google's eyes, all serving the same homepage&lt;/li&gt;
&lt;li&gt;It dilutes whatever ranking signal your actual homepage has, since Google now sees N copies of it at different URLs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a site that had literally zero custom 404 handling, this meant &lt;em&gt;any&lt;/em&gt; crawled dead link — a typo'd URL, an old removed page, a bot probing random paths — was quietly generating homepage duplicates in the index.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;Trivial once you know to look for it. In Astro (or basically any static site generator), you just need a page that generates &lt;code&gt;404.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
// src/pages/404.astro
import BaseLayout from '../layouts/BaseLayout.astro';
---
&amp;lt;BaseLayout title="Page Not Found" description="..."&amp;gt;
  &amp;lt;h1&amp;gt;404&amp;lt;/h1&amp;gt;
  &amp;lt;p&amp;gt;This page doesn't exist.&amp;lt;/p&amp;gt;
&amp;lt;/BaseLayout&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Astro (and most SSGs) automatically emits this as &lt;code&gt;dist/404.html&lt;/code&gt;, and Cloudflare Pages automatically serves it with a genuine 404 status for any unmatched route once it exists — no config needed, just the file being present.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; https://example.com/nonexistent-page
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;before: 200
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;after:  404
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The lesson
&lt;/h2&gt;

&lt;p&gt;If you're deploying a static site to Cloudflare Pages, Vercel, Netlify, or similar — check right now whether a random broken URL on your site returns 404 or 200. It's a two-second check and a five-minute fix, but it's exactly the kind of thing that never shows up unless you go looking, since the page &lt;em&gt;looks&lt;/em&gt; completely normal (it's literally rendering your homepage) — there's no visible error to notice.&lt;/p&gt;

&lt;p&gt;Source for the actual fix: &lt;a href="https://github.com/GRimkiller360/bracketly" rel="noopener noreferrer"&gt;https://github.com/GRimkiller360/bracketly&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>cloudflare</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I Implemented MD5 From Scratch in JavaScript (Because Web Crypto Won't)</title>
      <dc:creator>Bracketly</dc:creator>
      <pubDate>Fri, 17 Jul 2026 09:04:35 +0000</pubDate>
      <link>https://dev.to/ethan_5b3022150e2c07a4030/i-implemented-md5-from-scratch-in-javascript-because-web-crypto-wont-3cfj</link>
      <guid>https://dev.to/ethan_5b3022150e2c07a4030/i-implemented-md5-from-scratch-in-javascript-because-web-crypto-wont-3cfj</guid>
      <description>&lt;h1&gt;
  
  
  I Implemented MD5 From Scratch in JavaScript (Because Web Crypto Won't)
&lt;/h1&gt;

&lt;p&gt;While building &lt;a href="https://bracketly.pages.dev" rel="noopener noreferrer"&gt;Bracketly&lt;/a&gt; — a small set of free, client-side developer tools — I hit an annoying gap while writing the hash generator: the browser's native &lt;code&gt;crypto.subtle.digest()&lt;/code&gt; supports SHA-1, SHA-256, SHA-384, and SHA-512, but &lt;strong&gt;not MD5&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's deliberate. MD5 is cryptographically broken — collisions can be deliberately engineered — so the Web Crypto API spec simply doesn't include it. But MD5 is still one of the most-searched hash algorithms, because it's everywhere in non-security contexts: file integrity checksums, legacy system compatibility, cache keys, dedup fingerprints. People still need to compute it, even though nobody should use it for anything security-sensitive anymore.&lt;/p&gt;

&lt;p&gt;So: no native API, tool still needs to support it, only option left is implementing the algorithm myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The algorithm, briefly
&lt;/h2&gt;

&lt;p&gt;MD5 processes a message in 512-bit (64-byte) chunks through four rounds of 16 operations each — 64 operations total per chunk — each round using a different nonlinear function (&lt;code&gt;F&lt;/code&gt;, &lt;code&gt;G&lt;/code&gt;, &lt;code&gt;H&lt;/code&gt;, &lt;code&gt;I&lt;/code&gt;) mixing three of four 32-bit state words, plus a precomputed constant table &lt;code&gt;K&lt;/code&gt; (the integer parts of the sines of 1 to 64, in radians) and a set of per-round left-rotation amounts.&lt;/p&gt;

&lt;p&gt;The message has to be padded first: append a single &lt;code&gt;1&lt;/code&gt; bit, then zero bits until the length is congruent to 448 mod 512, then append the original bit-length as a 64-bit little-endian integer. Get this padding wrong by even one byte and every hash silently comes out wrong — there's no error, just garbage output that happens to be valid-looking hex.&lt;/p&gt;

&lt;p&gt;Here's the padding and main compression loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;rotl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint32Array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="mh"&gt;0xd76aa478&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xe8c7b756&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x242070db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xc1bdceee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* ...64 total */&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextEncoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;origLenBits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;padLen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;padded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;padLen&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;padded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;padded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DataView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;padded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setUint32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;padded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;origLenBits&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setUint32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;padded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;origLenBits&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mh"&gt;0x100000000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x67452301&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xefcdab89&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x98badcfe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;d0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x10325476&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;padded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;M&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint32Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUint32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;b0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;c0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                 &lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;             &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;              &lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;rotl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;a0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;b0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;c0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;d0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...serialize a0-d0 as little-endian hex&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trickiest part wasn't the algorithm itself, it was getting the &lt;strong&gt;endianness&lt;/strong&gt; right — MD5 spec is little-endian throughout (message word loading, final digest byte order), which is easy to get backwards if you're used to SHA's big-endian convention. Get it backwards and you get a hash that's wrong in a way that's hard to spot just by eyeballing it (still 32 hex chars, still looks plausible).&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying it
&lt;/h2&gt;

&lt;p&gt;Never trust a from-scratch crypto implementation without checking it against known-good vectors. RFC 1321 (and general convention) gives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;md5("")    → d41d8cd98f00b204e9800998ecf8427e
md5("abc") → 900150983cd24fb0d6963f7d28e17f72
md5("The quick brown fox jumps over the lazy dog") → 9e107d9d372bb6826bd81d3542a419d6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three matched on the first attempt after fixing the endianness bug above — which is a relief, because subtle bugs in hash implementations are exactly the kind of thing that pass casual testing and then produce wrong output on some inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it ended up
&lt;/h2&gt;

&lt;p&gt;It's live as one of the tools on &lt;a href="https://bracketly.pages.dev/tools/hash-generator" rel="noopener noreferrer"&gt;Bracketly&lt;/a&gt; alongside SHA-1/256/512 (which just call &lt;code&gt;crypto.subtle.digest&lt;/code&gt; directly, no reinventing needed there). Everything runs client-side — nothing typed in ever leaves the browser, which is the whole point of the site: a handful of free developer utilities (JSON formatter, Base64, JWT decoder, URL encoder, UUID generator, regex tester, color converter, timestamp converter) with no backend, no accounts, no tracking.&lt;/p&gt;

&lt;p&gt;Source is on GitHub if you want to see the rest: &lt;a href="https://github.com/GRimkiller360/bracketly" rel="noopener noreferrer"&gt;https://github.com/GRimkiller360/bracketly&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>showdev</category>
      <category>security</category>
    </item>
  </channel>
</rss>
