Skip to content

crypto/sha2: publish hash and block lengths in bytes - #1606

Merged
sergey-shandar merged 2 commits into
mainfrom
claude/sha2-byte-length-fields
Aug 16, 2026
Merged

crypto/sha2: publish hash and block lengths in bytes#1606
sergey-shandar merged 2 commits into
mainfrom
claude/sha2-byte-length-fields

Conversation

@sergey-shandar

Copy link
Copy Markdown
Contributor

Implements fjs/crypto/sha2/todo/byte-length-fields.md (deleted here).

Why

Sha2 published only bit counts, so every consumer needing bytes re-did the conversion — in two different spellings:

// hmac
const p = repeat(blockLength >> 3n)
// sign
const rep = repeat(divUp8(hf.hashLength))

Whether the two roundings agree was left for the reader to work out per site.

What

sha2(...) computes both once and the type publishes them:

readonly hashBytes: bigint
readonly blockBytes: bigint

hmac reads blockBytes, sign reads hashBytes, and divUp8 drops out of sign's imports entirely.

divUp8 is the spelling kept for both: it agrees with >> 3n on every SHA-2 variant, and it is the rounding RFC 6979 actually specifies (ceil(hlen/8)), so a hypothetical non-byte-multiple hashLengthsha2 takes it as a parameter — stays correct rather than silently truncating.

Verification

I checked the "the two roundings agree" premise rather than assuming it, across every variant:

hashLength hashBytes blockLength blockBytes
sha224 224 28 512 64
sha256 256 32 512 64
sha384 384 48 1024 128
sha512 512 64 1024 128
sha512x224 224 28 1024 128
sha512x256 256 32 1024 128

All equal >> 3n. (The TODO said "all four variants" — there are six.)

  • npx tsc clean; fjs test 2910 pass, 0 fail; npm run cov 100% aggregate, which Fail npm run cov if aggregate coverage falls under 100% #1605 now gates on.
  • New byteLengths proof covers all six, asserting each byte count against both its expected value and the bit length it derives from, so the identity is pinned rather than the numbers alone.
  • Differential on hmac, the consumer whose changed value feeds a branch (length(k) > blockLength): 6 variants × 10 key lengths straddling both block sizes (0, 1, 32, 63, 64, 65, 127, 128, 129, 200 bytes) × 5 message lengths = 300 digests, identical.
  • Differential on sign/computeK: 4 curves × 6 hashes × 4 messages = 96 signatures, identical.
  • Declaration emit shows exactly the two added fields and nothing else.

One note on method: my first hmac differential script was wrong — it passed a list where a Vec was expected and crashed on both sides, so cmp reported "identical" on two equal stack traces. I caught it, fixed the call, and added a row-count and non-empty-digest guard to both scripts so a silent failure cannot masquerade as a match again. The numbers above are from the corrected runs.

Changelog:

  • crypto/sha2: Sha2 publishes hashBytes and blockBytes, so consumers sizing byte buffers read them instead of converting bit lengths themselves

🤖 Generated with Claude Code

https://claude.ai/code/session_016HvbYkBMYWwQECL7myLhqs


Generated by Claude Code

Working notes; the PR title and description are the commit message.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016HvbYkBMYWwQECL7myLhqs
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016HvbYkBMYWwQECL7myLhqs
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
functionalscript a9635bc Commit Preview URL

Branch Preview URL
Aug 16 2026, 03:47 AM

@o2alexanderfedin o2alexanderfedin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked the rounding premise at runtime rather than assuming it, since divUp8 and >> 3n diverge for any bit length that isn't a multiple of 8. All six variants have both lengths ≡ 0 mod 8 — sha224 224/512, sha256 256/512, sha384 384/1024, sha512 512/1024, sha512x224 224/1024, sha512x256 256/1024 → hashBytes 28/32/48/64/28/32, blockBytes 64/64/128/128/128/128 — each matching >> 3n. The PR's table is accurate, including that there are six variants rather than the four the todo claimed.

Differential: 456/456 rows byte-identical against origin/main. 300 HMAC digests (6 variants × 10 key byte-lengths 0/1/32/63/64/65/127/128/129/200, straddling both the 64- and 128-byte block boundaries and the length(k) > blockLength branch, × 5 message lengths), 120 sign signatures (5 curves incl. secp521r1 × 6 hashes × 4 messages), 30 computeK nonces. RFC 4231 case 1 reproduces exactly for SHA-256 (b0344c61…2e32cff7) and SHA-512 (87aa7cde…3a126854), so the harness is comparing real output rather than two matched failures.

No half-migration: both fields derive in sha2(...) from the same inputs the old sites converted, and grep over fjs/crypto/ finds no remaining >> 3n / divUp8 / / 8n. hmac's residual blockLength uses are genuine bit quantities.

Proofs discriminate: byteLengths asserts against hand-written 28/32/48/64/64/128, and mutations hashBytes ±1n, blockBytes ±1n, and hashBytes: divUp8(chunkLength) each fail all six.

npx tsc exit 0; 2910 pass / 0 fail; npm run cov exit 0 at 100/100/100 under the new #1605 gate; ci-update leaves the tree clean.

@sergey-shandar
sergey-shandar added this pull request to the merge queue Aug 16, 2026
Merged via the queue into main with commit f9a276a Aug 16, 2026
19 checks passed
@sergey-shandar
sergey-shandar deleted the claude/sha2-byte-length-fields branch August 17, 2026 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants