169 lines
6.5 KiB
TeX
169 lines
6.5 KiB
TeX
\section{Whirlpool}
|
|
|
|
Whirlpool is a cryptographic hash function designed by Vincent Rijmen and Paulo
|
|
Barreto, first published in 2000 and standardized by ISO/IEC in 2004. It
|
|
produces a 512-bit digest from a message of arbitrary length, processing data
|
|
in 512-bit blocks. Its internal structure is inspired by the wide-pipe
|
|
Miyaguchi-Preneel construction and shares design principles with AES, using a
|
|
substitution-permutation network over an $8 \times 8$ matrix of bytes.
|
|
|
|
\vspace{1em}
|
|
|
|
Whirlpool maintains a state of eight 64-bit words, forming an $8 \times 8$
|
|
matrix of bytes. Each 512-bit block is processed in 10 rounds. Each round
|
|
applies four successive transformations to the state matrix: a byte
|
|
substitution, a column shift, a row mixing, and a round key addition.
|
|
|
|
\vspace{1em}
|
|
|
|
The padding scheme appends a single \texttt{1} bit, followed by \texttt{0}
|
|
bits until the message length is congruent to 256 bits modulo 512. The original
|
|
message length in bits is then appended as a 256-bit big-endian integer,
|
|
bringing the total padded length to an exact multiple of 512 bits. Whirlpool
|
|
uses a 256-bit length field (rather than the 64-bit field of MD5 and SHA-256)
|
|
to support messages up to $2^{256} - 1$ bits in length.
|
|
|
|
\vspace{1em}
|
|
|
|
\textbf{Arithmetic in $\mathrm{GF}(2^8)$.}
|
|
A \textbf{finite field} (or Galois field) is a finite set in which addition,
|
|
subtraction, multiplication and division (by any non-zero element) are all
|
|
well-defined and satisfy the usual algebraic laws. The simplest example is
|
|
$\mathrm{GF}(2) = \{0, 1\}$, where addition is XOR and multiplication is AND.
|
|
|
|
\vspace{1em}
|
|
|
|
$\mathrm{GF}(2^8)$ extends this to 256 elements by representing each element
|
|
as a polynomial of degree less than 8 with coefficients in $\{0, 1\}$. A byte
|
|
$b_7 b_6 \cdots b_0$ encodes the polynomial
|
|
$b_7 x^7 + b_6 x^6 + \cdots + b_0$; for example,
|
|
\texttt{0b10100011} $= x^7 + x^5 + x + 1$.
|
|
|
|
\vspace{1em}
|
|
|
|
This construction is analogous to modular arithmetic: just as
|
|
$\mathbb{Z}/p\mathbb{Z}$ is a field because $p$ is prime, the set of
|
|
polynomials with binary coefficients forms a field when reduced modulo an
|
|
\emph{irreducible} polynomial --- one that cannot be factored. Without this
|
|
reduction, multiplying two polynomials could produce a degree greater than 7,
|
|
stepping outside the 256-element set. Reducing modulo an irreducible polynomial
|
|
of degree 8 keeps every result within one byte, and guarantees that every
|
|
non-zero element has a multiplicative inverse.
|
|
|
|
\vspace{1em}
|
|
|
|
\textbf{Addition} is coefficient-wise addition modulo 2, equivalent to a
|
|
bitwise XOR (there is no carry: $1 + 1 = 0$):
|
|
\begin{align*}
|
|
a + b = a \oplus b
|
|
\end{align*}
|
|
|
|
\textbf{Multiplication by $x$} (called \emph{xtime}) is a left shift by one
|
|
bit, followed by a conditional reduction: if the original high bit was 1, the
|
|
degree of the result would reach 8 and must be reduced modulo the irreducible
|
|
polynomial $p(x) = x^8 + x^4 + x^3 + x^2 + 1$ (\texttt{0x11d}), which means
|
|
XORing with its low byte \texttt{0x1d}:
|
|
\begin{align*}
|
|
\mathrm{xtime}(a) =
|
|
\begin{cases}
|
|
a \ll 1 & \text{if } b_7 = 0 \\
|
|
(a \ll 1) \oplus \texttt{0x1d} & \text{if } b_7 = 1
|
|
\end{cases}
|
|
\end{align*}
|
|
|
|
\textbf{Multiplication by an arbitrary element} decomposes the multiplier into
|
|
powers of 2, applies xtime repeatedly for each power, then combines the results
|
|
with XOR. For example, multiplying by \texttt{0x05} $= x^2 + 1$:
|
|
\begin{align*}
|
|
\texttt{0x05} \cdot a = \mathrm{xtime}(\mathrm{xtime}(a)) \oplus a
|
|
\end{align*}
|
|
|
|
\newpage
|
|
|
|
Each round applies the following four transformations in order:
|
|
|
|
\medskip
|
|
|
|
\textbf{SubBytes} replaces each byte of the state matrix by its image under the
|
|
Whirlpool S-box, a fixed 256-entry lookup table defined in the Whirlpool
|
|
specification.
|
|
|
|
\medskip
|
|
|
|
\textbf{ShiftColumns} cyclically shifts each column $j$ of the state matrix
|
|
upward by $j$ positions, producing a transposition that spreads bytes across
|
|
rows. Formally, if $a_{i,j}$ denotes the byte at row $i$, column $j$ of the
|
|
state matrix, ShiftColumns produces:
|
|
|
|
\begin{align*}
|
|
b_{i,j} = a_{i',\ j} \quad \text{where } i' = (i - j) \bmod 8
|
|
\end{align*}
|
|
|
|
\medskip
|
|
|
|
\textbf{MixRows} multiplies each row of the state matrix by a fixed circulant
|
|
MDS matrix over $\mathrm{GF}(2^8)$ with irreducible polynomial
|
|
$x^8 + x^4 + x^3 + x^2 + 1$, providing diffusion across the eight bytes of
|
|
each row. The MDS matrix is fully determined by its first row
|
|
$(c_0,\ c_1,\ \ldots,\ c_7)$; the entry at row $j$, column $k$ equals
|
|
$c_{(j-k) \bmod 8}$. Formally, for each row $i$, each output byte $b_{i,j}$
|
|
is computed as:
|
|
|
|
\begin{align*}
|
|
b_{i,j} = \bigoplus_{k=0}^{7} c_{(j-k) \bmod 8} \cdot a_{i,k}
|
|
\end{align*}
|
|
|
|
\noindent where $\cdot$ denotes multiplication in $\mathrm{GF}(2^8)$ and $\oplus$ denotes XOR.
|
|
|
|
\medskip
|
|
|
|
\textbf{AddRoundKey} XORs the state with the current round key:
|
|
|
|
\begin{align*}
|
|
S \leftarrow S \oplus K[r]
|
|
\end{align*}
|
|
|
|
The S-box and the MDS matrix coefficients are fixed tables defined in the
|
|
Whirlpool specification; their values are too large to reproduce here. The
|
|
round constants $\mathrm{RC}[r]$, $r \in \mathbb{N},\ 1 \leq r \leq 10$, are
|
|
however directly derived from the S-box. Each $\mathrm{RC}[r]$ is an 8-word
|
|
state where only the first word is non-zero:
|
|
|
|
\begin{align*}
|
|
\mathrm{RC}[r][0] &= \sum_{k=0}^{7} S[8(r-1)+k] \cdot 2^{8(7-k)} \\
|
|
\mathrm{RC}[r][j] &= 0 \quad \forall j \in \mathbb{N},\ 1 \leq j \leq 7
|
|
\end{align*}
|
|
|
|
\noindent Their role is to break symmetry in the key schedule: without them, a
|
|
symmetric input state would produce symmetric round keys, weakening the internal
|
|
block transformation.
|
|
|
|
\vspace{1em}
|
|
|
|
The round keys $K[r]$, $r \in \mathbb{N},\ 0 \leq r \leq 10$, are derived from
|
|
the current hash state. $K[0]$ is set to the state before processing the block.
|
|
Each subsequent key is obtained by applying the round function to the previous
|
|
key with a precomputed round constant, where $\text{Round}(S, K)$ denotes the
|
|
successive application of SubBytes, ShiftColumns, MixRows, and AddRoundKey with
|
|
key $K$ to state $S$:
|
|
|
|
\begin{align*}
|
|
K[0] &= H \\
|
|
K[r] &= \text{Round}(K[r-1],\ \mathrm{RC}[r]) \quad r \in \mathbb{N},\ 1 \leq r \leq 10
|
|
\end{align*}
|
|
|
|
The block $M$ is then encrypted using these keys under a wide-pipe construction.
|
|
The final state update follows the Miyaguchi-Preneel scheme:
|
|
|
|
\begin{align*}
|
|
H \leftarrow E(H,\ M) \oplus M \oplus H
|
|
\end{align*}
|
|
|
|
\noindent where $E(H, M)$ denotes the encryption of $M$ with key schedule
|
|
derived from $H$.
|
|
|
|
\vspace{1em}
|
|
|
|
The state is initialized to all zeros. After all blocks have been processed,
|
|
the eight 64-bit state words are serialized in big-endian order to produce the
|
|
512-bit digest.
|