What is the reason to have these 3 functions instead of just a standalone function that returns an output hash for an input bitstring?
This allows to compute the hash of a piece of information that is made available by segments, rather than as a single memory block. This comes handy in many situations, including
- When the data is too large to fit memory (e.g. hash of a large file)
- When the data to hash is the content of many network packets (the alternative would require a memory buffer as large as the sum of the length of the packets, and a copy of each packet into that, which is time consuming and kills the cache).
- When it's desired to perform activities at time intervals smaller than the duration of the whole hash, in a single-thread context. We break the data into pieces, and perform the activity between the hash of individual pieces.
- When several hashes must be computed concurrently (e.g. multiple users of a server with less threads than users).
What exactly does CTX stand for?
Context. It holds the current state of the hash being computed, typically the 32 bytes of the current chaining value, a number (typically at most 64) of messages bytes not hashed yet, and the length of the data so far (typically on 8 bytes). A typical SHA-256 context is thus 104 bytes, or slightly more.