public class GF256AES
extends java.lang.Object
The AES suffix names that specific irreducible polynomial: GF(2^8) is a
single field up to isomorphism but admits many representations, and the AES
choice is by far the most common (also used by SM4, GHASH's sibling fields,
etc.). The polynomial alone pins down the arithmetic — e.g. Rainbow's GF(2^8)
uses a tower basis whose products differ, so it deliberately does not share
this class. Callers relying on the AES element encoding should depend on the
name, not just "GF(256)".
Shared home for the word-parallel bitsliced scalar-times-vector multiply used
by the multivariate / MPC-in-the-head schemes (SDitH, UOV, ...). Companion to
GF16 for the GF(2^4) nibble field.
| Modifier and Type | Method and Description |
|---|---|
static int |
inv(int a)
Constant-time GF(256) multiplicative inverse over 0x11b via the Fermat
addition chain
a^254 = a^-1 (since a^255 = 1 for nonzero
a). |
static int |
mul(int a,
int b)
Constant-time GF(256) scalar multiply over the AES polynomial 0x11b:
returns
a * b. |
static long |
mulFx8(int s,
long v)
Word-parallel constant-time GF(256) scalar-times-vector multiply: returns
s * v where v packs eight GF(256) elements, one per byte
lane, and the result packs the eight products in the same lanes. |
static int |
sqr(int a)
Constant-time GF(256) squaring over 0x11b.
|
public static int mul(int a,
int b)
a * b. There is no table lookup and no data-dependent branch
— safe to feed secret operands. This is the scalar companion of
mulFx8(int, long) and is byte-identical to the per-scheme forms it
replaces (UOV's mul256, SDitH's mulNaive, MQOM's gf256Mult).public static int sqr(int a)
a^2 is just the bit-spread of a (interleave a zero between
each bit), reduced mod 0x11b.public static int inv(int a)
a^254 = a^-1 (since a^255 = 1 for nonzero
a). The chain maps 0 -> 0, so no data-dependent zero check
is needed and none is done: branching on zero-ness would leak whether a
(secret-derived) value was singular. No table is used. The seven squarings
go through the dedicated sqr(int); the four genuine products
through mul(int, int).public static long mulFx8(int s,
long v)
s * v where v packs eight GF(256) elements, one per byte
lane, and the result packs the eight products in the same lanes.
Algorithm: s*v = XOR_k s_k (x^k . v) over the 8 bits s_k
of the scalar, where x^k . v is k-fold GF(256) doubling
(xtime) of every lane. xtime is the branchless SWAR step
((v<<1) & 0xFE..) ^ ((v>>>7 & 0x01..) * 0x1b), and each scalar bit
selects via the mask -(s_k) (0 or -1). No table and no
data-dependent branch, so it is safe to feed secret scalars (the operand
of a secret-share multiply-accumulate).