EVP_DigestUpdate chunked hashing or EVP_DigestEx single-call for paginated datasets
0 reputation · 19 Sept 2021, 21:48 UTC
0 reputation · 19 Sept 2021, 21:48 UTC
Compute one message digest over a large dataset read in bounded pages, keeping memory usage constant instead of loading the full input into memory.
OpenSSL provides EVP_DigestUpdate for incremental hashing and EVP_DigestEx for a single-call digest. The incremental API avoids loading the entire dataset but requires per-chunk context handling. OpenSSL 3.x EVP_MD_CTX reset semantics differ from 1.1.1, and it is unclear whether one context can be safely reset and reused across unrelated digest operations without re-initialization.
35275 reputation · 20 Sept 2021, 05:04 UTC
Use a single EVP_MD_CTX for the entire dataset. Call EVP_DigestInit_ex once, then EVP_DigestUpdate for each page, then EVP_DigestFinal_ex once. Do not create a fresh context per page and do not call EVP_MD_CTX_reset between pages of the same digest operation. EVP_DigestEx is a single-shot convenience function that requires the full input buffer; it cannot process paginated input incrementally.
Update calls, one Final. Each Update processes the page buffer in place with no extra copies.EVP_MD_CTX_reset() (3.x) and EVP_MD_CTX_cleanup() (1.1.1) clear algorithm-specific state and any keyed-hash keys but keep the allocated context structure. They are intended only when you finish one complete digest and want to start a completely new, unrelated digest with the same context object. Between Update calls of the same digest stream, do not call either function.
If your pagination logic interleaves multiple independent digest operations (e.g., hashing several files concurrently), allocate one EVP_MD_CTX per digest stream. Do not share a single context and reset it between files — separate contexts are simpler and avoid any cross-contamination risk.
Update.openssl dgst -sha256 <file> or a single-shot EVP_DigestEx call on the full buffer.EVP_MD_CTX_free.Are you hashing a single logical dataset across pages, or multiple independent datasets that happen to be read with the same pagination loop? The answer determines whether you need one context or several — but in either case, you never reset between pages of the same dataset.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 20 Sept 2021, 07:02 UTC
For one digest over paginated reads, reuse a single EVP_MD_CTX: initialize once with EVP_DigestInit_ex, call EVP_DigestUpdate for each page, and finalize once after the last page. Do not reset or finalize between pages; doing so produces a prefix digest, not the cumulative hash. EVP_DigestEx requires a contiguous buffer, so it cannot stream pages without materializing the full dataset and breaks the constant-memory constraint. When starting an unrelated digest, finalize the prior context, then either allocate a new context or call EVP_MD_CTX_reset followed by EVP_DigestInit_ex; verify reset semantics against the installed OpenSSL 3.x or 1.1.1 library before reusing contexts across digest boundaries.