Skip to content

Fix SHA3/Keccak large-buffer Absorb OutOfRange (closes #94) - #100

Merged
MHumm merged 3 commits into
MHumm:developmentfrom
omonien:pr-fix-sha3-large-buffer
Sep 6, 2026
Merged

Fix SHA3/Keccak large-buffer Absorb OutOfRange (closes #94)#100
MHumm merged 3 commits into
MHumm:developmentfrom
omonien:pr-fix-sha3-large-buffer

Conversation

@omonien

@omonien omonien commented Jul 23, 2026

Copy link
Copy Markdown

For Markus — theme: product bug fix (HashBenchmark / large messages, GitHub #94)

Addresses issue #94 (HashBenchmark OutOfRange in Keccak Absorb) with two root causes — both fixed here.

Cause 1 — Demo API misuse (intermittent)

CalcBuffer(@FBenchmarkBuffer[0], Size) passes a pointer-to-pointer because const Buffer is already by reference. Failures depended on stack layout — hard to reproduce, easy to mis-blame on the library.

Fix: CalcBuffer(FBenchmarkBuffer[0], BufferSize) + comment; drop the PwdHashBuf workaround so password and non-password hashes share one path.

Cause 2 — Library: 64 KiB typed view + multi-round pointer walk

  1. TBABytes = array[0..65535] with {+} in the SHA-3 section → data^[i] past 64 KiB raised ERangeError on large messages (e.g. 1 MiB).
  2. THash_SHA3Base.Calc advanced a PBABytes pointer with Inc(..., RoundSize), which scales by SizeOf(TBABytes), not by bytes — multi-round absorption for large inputs walked the wrong addresses.

Fix:

  • Open-ended TBABytes bound (typed view only; no allocation change)
  • Walk message with PByte; cast only at Absorb

Regression tests

TestCalcBufferLargeMessage (Keccak-224, 1 MiB, HashBenchmark fill pattern):

  • One-shot CalcBuffer / CalcBytes
  • Multi-round Calc vs incremental small-chunk Init/Calc/Done
  • Known digest (PyCryptodome)

Files

File Role
Source/DECHash.pas Absorb bounds + byte-step multi-round Calc
Demos/HashBenchmark_FMX/MainFormHashBenchmark.pas Correct CalcBuffer usage
Unit Tests/Tests/TestDECHashSHA3.pas 1 MiB regression

Scope boundary

In this PR Not in this PR
Large-message Absorb/Calc correctness Keccak CAVP/Unicode test vector cleanup (separate PR)
HashBenchmark demo call site GCM

Risk

Medium — core SHA-3 sponge path for all SHA-3/Keccak digests. Mitigated by explicit 1 MiB multi-round regression and existing KATs.

Independence

Independent of DUnitX and GCM. Complements the Keccak test PR; this one is the library large-buffer fix.

Test plan

  • Full unit test suite with range checks on
  • TestCalcBufferLargeMessage green
  • Optional: run HashBenchmark_FMX through Keccak-224 with large buffer

Closes #94 (when merged).

omonien added 3 commits July 27, 2026 11:17
Widen TBABytes beyond 64 KiB so {$R+} no longer raises in Absorb for
multi-megabyte messages (HashBenchmark path). HashBenchmark now uses the
correct CalcBuffer(FBenchmarkBuffer[0], Size) form without a spurious @.
Add Keccak-224 1 MiB CalcBuffer regression with known digest.
THash_SHA3Base.Calc used PBABytes for DataPtr; Inc(DataPtr, RoundSize)
scaled by SizeOf(TBABytes). Walk with PByte and cast only for Absorb.
Use 64 KiB Absorb rounds so large messages exercise multi-round DataPtr
advance. Extend TestCalcBufferLargeMessage to compare one-shot multi-round
Calc against incremental small-chunk Init/Calc/Done plus known digest.
@omonien
omonien force-pushed the pr-fix-sha3-large-buffer branch from d04bfaf to c57347d Compare July 27, 2026 09:17
@MHumm
MHumm merged commit 0897e12 into MHumm:development Sep 6, 2026
@omonien

omonien commented Sep 6, 2026

Copy link
Copy Markdown
Author

Hallo Markus,

kurze Klarstellung: die geänderte Tag-Zeile in gcmEncryptExtIV256_large.rsp kommt aus PR #99 (GCM multi-call / GHASH+CTR), nicht aus #100. #100 ändert nur SHA-3/Keccak und den HashBenchmark.

Zur Datei selbst: Das ist keine offizielle NIST-CAVS-Datei, sondern eine große DEC-eigene Fixture im CAVS-.rsp-Format (2022, denovosoftware, für TestEncodeLargeStream). Damals war der Test bewusst rot, weil der GCM-Whole-Stream-Pfad bei großen Streams den falschen Tag lieferte.

Beim Fix in #99 stimmte der Ciphertext bereits mit AES-GCM überein, der erwartete Tag in der .rsp nicht. Den neuen Wert

Tag = 1b668695f48ea9fb1b9c8a5e178605c3

habe ich unabhängig mit PyCryptodome (AES-GCM) über denselben Key/IV/PT/AAD nachgerechnet und die Fixture daran angepasst. Der alte Tag 1355862d917943aaa7ea7d18a8ed5b2f war damit inkonsistent.

Wenn du willst, poste ich dir gerne noch das kleine Python-Snippet dazu.

Viele Grüße
Olaf

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.

2 participants