\section{Preliminaries} This section defines the terminology used throughout the document. The concepts introduced here are general to cryptographic hash functions and apply to all algorithms described in subsequent sections. \vspace{1em} A \textbf{bit} is the smallest unit of information, taking a value of either 0 or 1. A \textbf{byte} is a group of eight bits, and is the standard unit of data storage and transmission. A \textbf{word} is a fixed-size integer used internally by a hash algorithm --- MD5 and SHA-256 operate on 32-bit words, while Whirlpool operates on 64-bit words. \vspace{1em} \textbf{Endianness} refers to the byte order used when storing a multi-byte integer in memory. In \textbf{little-endian} order, the least significant byte is stored first; in \textbf{big-endian} order, the most significant byte is stored first. This distinction matters when serializing the internal state to produce the final digest --- MD5 uses little-endian, while SHA-256 and Whirlpool use big-endian. \vspace{1em} A \textbf{message} is the arbitrary-length input fed to a hash function. The \textbf{digest} is the fixed-size output it produces. A hash function is said to be \textbf{one-way} if it is computationally infeasible to recover any input that produces a given digest. A \textbf{collision} occurs when two distinct messages produce the same digest; a hash function is considered broken when collisions can be found efficiently. \vspace{1em} Hash functions process their input in fixed-size chunks called \textbf{blocks}. Since the message length is rarely a multiple of the block size, \textbf{padding} is appended to the last block to bring it to the required length. The \textbf{state} is a set of words initialized to fixed constants and updated after each block; it accumulates the result of the computation and is serialized into the digest at the end. The \textbf{compression function} is the core transformation applied to each block --- it takes the current state and one block of data, and produces a new state. \vspace{1em} The \textbf{Miyaguchi-Preneel} construction is a way to build a compression function from a block cipher $E$. Given a current state $H$ and a message block $M$, it produces a new state as: \begin{align*} H \leftarrow E(H,\ M) \oplus M \oplus H \end{align*} \noindent where $E(H, M)$ denotes the encryption of $M$ using $H$ as the key. The XOR with both $M$ and $H$ ensures that the output cannot be trivially inverted even if $E$ is known. \vspace{1em} The \textbf{wide-pipe} construction is a variant of Merkle-Damgård where the internal state is wider than the final digest. This makes collision attacks harder: an attacker targeting the output must first find a collision in the larger internal state, which requires significantly more work than attacking the digest directly.