Imagine de ansamblu: acest cod trebuie să calculeze polinomul ireductibil binar modulo invers $P$ a fiecărui polinom binar diferit de zero $R$ de grad mai mic decât cel de $P$. În acest sens, a selectat un polinom generator $G=1+x$, și tabulează $Q_i=G^i\bmod P$, care atinge toate cele dorite $R$. Inversul multiplicativ al $R=Q_i$ este $Q_{255-i}$.
Acest cod evaluează AES S-box și este invers după cum urmează:
(blocul de cod care începe în încerca
) Evaluează p = 0x11b = 283
care reprezintă polinomul binar $P=1+x+x^3+x^4+x^8$ ca număr întreg: valoarea obţinută la evaluarea acestui polinom pentru întreg $x=2$. Această convenție comună este utilizată în AES pentru a mapa polinoamele binare la numere întregi.
(blocul de cod care începe în lasa t
) Calculează tabelul t[i]
reprezentând polinomul binar $Q_i=(1+x)^i\bmod P$ conform acestei convenții. Acea $Q_i$ este calculată în funcție de recurență $Q_{i+1}=Q_i\,(1+x)\bmod P$ cu $Q_0=1$, traducând¹ în t[i+1] = t[i] ^ ((t[i] << 1) ^ ((t[i] >>> 7) * p))
cu t[0] = 1
conform convenției menționate.
De exemplu: $Q_0$ este polinomul (binar). $1$, reprezentată de t[0] = 1
. $Q_1=1+x$, reprezentată de t[1] = 3
. $Q_2=(1+x)^2=1+x^2$, reprezentată de t[2] = 5
. $Q_7=(1+x)^7=1+x+x^2+x^3+x^4+x^5+x^6+x^7$, reprezentată de t[2] = 0xff = 255
. $Q_8=(1+x)^8\bmod P=(1+x^8)\bmod P=x+x^3+x^4$, reprezentată de t[8] = 0x1a = 26
.
(blocul de cod care începe în lasa Sbox
) Tabulare $Q_i=(1+x)^i\bmod P$ a fost util pentru că $(1+x)^{255}\bmod P=1$, prin urmare $Q_{255-i}$ este inversul multiplicativ al $Q_i$. Și $Q_i$ atinge toate polinoamele binare diferite de zero de grad $<8$ (acesta este $1+x$ este un generator). Prin urmare, întreg t[255 - i]
reprezintă inversul multiplicativ al polinomului acel număr întreg t[i]
reprezintă. Și când în buclă i
merge de la 0
la 254
care dă inversul multiplicativ al fiecăruia dintre cele 255 de polinoame diferite de zero de grad $<8$. Bucla apoi aplică doar transformarea afină specificată în restul definiția AES S-box. Polinomul zero este cu majuscule speciale.
De exemplu: când în buclă i = 8
, t[i]
este t[8] = 0x1a = 26
reprezentând $Q_8=x+x^3+x^4$, și t[255-i]
(merge la X
, fără legătură cu $x$) este t[247] = 0xfd = 253
reprezentând polinomul $Q_{247}=1+x^2+x^3+x^4+x^5+x^6+x^7$. Acea $Q_{247}$ este inversul multiplicativ al $Q_8$. După definiția casetei S AES, rămâne doar să se aplice transformarea afină² la X
, apoi setați rezultatul în Sbox[t[i]] = Sbox[26]
.
(funcția inversă
) Tabelul invers este calculat prin căutarea fiecărei intrări din tabel. Asta funcționează, dar este ineficient. InvSbox[i] = sbox.indexOf(i);
ar putea fi înlocuite cu cele mai simple și mai eficiente InvSbox[sbox[i]] = i;
.
¹ Justificare: în t[i+1] = t[i] ^ ((t[i] << 1) ^ ((t[i] >>> 7) * p))
t[i]
este un număr întreg în $[0,2^8)$ si reprezinta $Q_i$ de grad $<8$
t[i] << 1
este un număr întreg par în $[0,2^9)$ si reprezinta $Q_i\,x$.
t[i] >>> 7
este fie 0
sau 1
. Este coeficientul termenului de comandă $x^7$ în $Q_i$.
(t[i] >>> 7) * p
este în mod corespunzător fie 0
sau 0x11b = 283
, reprezentând $0$ sau $P$.
(t[i] << 1) ^ ((t[i] >>> 7) * p)
reprezintă în mod corespunzător $(Q_i\,x)$ sau $(Q_i\,x)+P$, și (prin examinarea celor două cazuri) este un număr întreg în $[0,2^8)$, reprezintă astfel un polinom binar de grad $<8$, care astfel este $(Q_i\,x)\bmod P$.
t[i] ^ ((t[i] << 1) ^ ((t[i] >>> 7) * p))
este astfel un număr întreg în $[0,2^8)$ si reprezinta $Q_i+(Q_i\,x)\bmod P)=Q_i\,(1+x)\bmod P=Q_{i+1}$, de grad $<8$.
În C, idiomul standard în timp constant probabil pentru această expresie ar fi (în esență cu & -
folosit în loc de înmulțire):
t[i+1] = t[i] ^ ((t[i] << 1) ^ (p & -(t[i] >> 7)))
.
Notă: unii compilatori C prea zeloși vor latra greșit la -
, tace-i.
² Declarația x |= x << 8;
dublează biții în variabilă X
(reprezentând inversul modular al $Q_i$) astfel încât deplasările ulterioare la dreapta să devină echivalente cu rotația atunci când vine vorba de cei 8 biți de ordin inferior. Declaratia x ^= (x >> 4) ^ (x >> 5) ^ (x >> 6) ^ (x >> 7);
implementează matricea circulantă multiplicare. Atunci ^ 0x63
(reprezentând polinom $1+x+x^5+x^6$) este adunarea constantă și & 0xFF
păstrează cei 8 biți de ordin inferior (termeni de grad $<8$), anulând duplicarea.