# Alle folgenden Funktionen sind genauso benannt wie im Skript. Sie verlangen jeweils als Eingabe eine 4X4-Matrix m deren # Eintraege Elemente aus dem Endlichen Koerper F2^28 sind. # Die Funktion HexToGF256 teilt einen gegebenen Hexadezimalstring der Laenge 32 in Hexadezimalstrings der Laenge 2 auf. Dann wird jeweils # jeder 2-Hexadezimalstring zu einem Polynom in w vom Grad <= 7. Dies ist analog zu der Aufteilung eines gegebenen 128-Bit-Strings # in 8-Bit-Strings. # Die 4x4-Matrix m soll Spaltenweise aufgefuellt werden, d.h. gibt der Aufruf von HexToGF256 die Liste [a1,a2,a3,a4,a5,a6,...] # zurueck, so besteht die erste Spalte von m aus [a1,a2,a3,a4], die zweite aus [a5,a6,...] usw. # AddRoundKey := function(m, kli) # #Verlangt als ersten Parameter die 4x4-Matrix m (Klartext) und als zweiten einen Schluessel aus dem Key-Schedule # return m + kli; end; phi := function(b) local k0x, x, k, z, f, g, h, res; k0x := PolyAlg(FF(2), "x"); x := Poly(k0x, [1,0]); k := FFEltFF(b); z := FFGenerator(k); f := Poly(k0x, Reversed(FFEltToList(b))); h := x^4 + x^3 + x^2 + x + 1; g := x^6 + x^5 + x + 1; res := (h * f + g) mod (x^8 + 1); res := Eval(PolyMove(res, k), z); return res; end; phiinv := function(b) local k0x, x, k, z, f, g, h, res; k0x := PolyAlg(FF(2), "x"); x := Poly(k0x, [1,0]); k := FFEltFF(b); z := FFGenerator(k); f := Poly(k0x, Reversed(FFEltToList(b))); h := x^6 + x^3 + x; g := x^2 + 1; res := (h * f + g) mod (x^8 + 1); res := Eval(PolyMove(res, k), z); return res; end; FieldInv := function(b) if not _IsZero(b) then b := 1/b; fi; return b; end; SubstBytes := function(m) local l; l := List([1..4], i->List([1..4], j->phi(FieldInv(m[i][j])))); IsMat(l); return l; end; SubstBytesInv := function(m) local l; l := List([1..4], i->List([1..4], j->FieldInv(phiinv(m[i][j])))); IsMat(l); return l; end; ShiftRows := function(m) local l, i, j; l := [ [], [], [], [] ]; for i in [1..4] do for j in [1..4] do l[i][j] := m[i][(j + i - 2) mod 4 + 1]; od; od; IsMat(l); return l; end; ShiftRowsInv := function(m) local l, i, j; l := [ [], [], [], [] ]; for i in [1..4] do for j in [1..4] do l[i][j] := m[i][(j - i) mod 4 + 1]; od; od; IsMat(l); return l; end; MixColumns := function(m) local k, z, t; k := FFEltFF(m[1][1]); z := FFGenerator(k); t := [ [z, z+1, 1, 1], [1, z, z+1, 1], [1, 1, z, z+1], [z+1, 1, 1, z] ]; IsMat(t); return t * m; end; MixColumnsInv := function(m) local k, z, t; k := FFEltFF(m[1][1]); z := FFGenerator(k); t := [ [z, z+1, 1, 1], [1, z, z+1, 1], [1, 1, z, z+1], [z+1, 1, 1, z] ]; IsMat(t); t := MatInv(t); return t * m; end; ########################################################################## # # Key schdeule # SubstWord := function(w) local t, l; t := [ phi(FieldInv(w[1][1])), phi(FieldInv(w[1][2])), phi(FieldInv(w[1][3])), phi(FieldInv(w[1][4])) ]; IsMat(t); return t; end; RotWord := function(w) local t; t := [ w[1][2], w[1][3], w[1][4], w[1][1] ]; IsMat(t); return t; end; fff := function(j, w, b) # # Funktion f # local z; if j mod b = 0 then z := FFGenerator(FFEltFF(w[1][1])); return SubstWord(RotWord(w)) + Mat( [z^((j/b - 1)), 0, 0, 0] ); elif b > 6 and j mod b = 4 then return SubstWord(w); else return w; fi; end; KeySchedule := function(K, b, n) # #Erzeugt die Liste der Schluessel k1 bis kn, wobei K der Schluessel ist. b und n sind so wie im Skript. # local j, w, kl; w := List([0..b-1], i->Mat( [ K[i*4+1], K[i*4+2], K[i*4+3], K[i*4+4] ] )); for j in [b..4*n+3] do w[j+1] := w[j-b+1] + fff(j, w[j-1+1], b); od; kl := List([0..n], i->Mat([ w[i*4+1], w[i*4+2], w[i*4+3], w[i*4+4] ]) ); kl := List([0..n], i->MatTrans(kl[i+1])); return kl; end; HexToGF256 := function(s, k) # # Input: # s is a hexadecimal string of even length. # k is GF_256 = GF_2[z]. # Output: # is a list of bytes (e.g. "10" --> z^4) # local k0, k0x, x, f, k, z, trans, B, i; if not Length(s) mod 2 = 0 then return false; fi; # Remark: Do not create k here because for two invocations # we get isomoprhic but different k's and then adding of elements # doesn't work ... z := FFGenerator(k); trans := function(c) local hb; if c = '0' then hb := 0*z; elif c = '1' then hb := 1 + 0*z; elif c = '2' then hb := z; elif c = '3' then hb := 1 + z; elif c = '4' then hb := z^2; elif c = '5' then hb := 1 + z^2; elif c = '6' then hb := z + z^2; elif c = '7' then hb := 1 + z + z^2; elif c = '8' then hb := z^3; elif c = '9' then hb := 1 + z^3; elif c = 'A' then hb := z + z^3; elif c = 'B' then hb := 1 + z + z^3; elif c = 'C' then hb := z^2 + z^3; elif c = 'D' then hb := 1 + z^2 + z^3; elif c = 'E' then hb := z + z^2 + z^3; elif c = 'F' then hb := 1 + z + z^2 + z^3; else return false; fi; return hb; end; B := []; for i in [1..Length(s)/2] do B[i] := trans(s[2*i-1])*z^4 + trans(s[2*i]); od; return B; end; GF256ToHex := function(B) # # Inverse to HexToGF256. # local k0, k0x, x, trans, b, s, l1, l, l2; k0 := FF(2); k0x := PolyAlg(k0, "x"); x := Poly(k0x, [1,0]); trans := function(hb) local c; if hb = 0*x then c := '0'; elif hb = 1 + 0*x then c := '1'; elif hb = x then c := '2'; elif hb = 1 + x then c := '3'; elif hb = x^2 then c := '4'; elif hb = 1 + x^2 then c := '5'; elif hb = x + x^2 then c := '6'; elif hb = 1 + x + x^2 then c := '7'; elif hb = x^3 then c := '8'; elif hb = 1 + x^3 then c := '9'; elif hb = x + x^3 then c := 'A'; elif hb = 1 + x + x^3 then c := 'B'; elif hb = x^2 + x^3 then c := 'C'; elif hb = 1 + x^2 + x^3 then c := 'D'; elif hb = x + x^2 + x^3 then c := 'E'; elif hb = 1 + x + x^2 + x^3 then c := 'F'; else return false; fi; return c; end; s := []; for b in B do l := Poly(k0x, Reversed(FFEltToList(b))); l1 := l mod x^4; l2 := (l - l1) / x^4; Add(s, trans(l2)); Add(s, trans(l1)); od; return s; end; AESEncipher := function(K, m) # Input: # m hexadecimal string of 128 bits # K hexadecimal string of 128 or 192 or 256 bits. # # Output: # c = hexdecimal string of 128 bit. local k0,k0x,x,f,k,m; # Set up the finite field. k0 := FF(2); k0x := PolyAlg(FF(2), "x"); x := Poly(k0x, [1,0]); f := x^8 + x^4 + x^3 + x + 1; k := FF(f); m := HexToGF256(m, k); K := HexToGF256(K, k); ### ..... end; AESDecipher := function(K, m) local k0, k0x, f, k; k0 := FF(2); k0x := PolyAlg(FF(2), "x"); x := Poly(k0x, [1,0]); f := x^8 + x^4 + x^3 + x + 1; k := FF(f); m := HexToGF256(m, k); K := HexToGF256(K, k); ### .... end; Entschluesseln Sie mit AES folgende Chiffre-Texte: KEY1 := "00010203050607080A0B0C0D0F101112"; PT1 := ? CT1 := "D8F532538289EF7D06B506A4FD5BE9C9"; KEY2 := "14151617191A1B1C1E1F202123242526"; PT2 := ? CT2 := "59AB30F4D4EE6E4FF9907EF65B1FB68C"; KEY3 := "00010203050607080A0B0C0D0F10111214151617191A1B1C"; PT3 := ? CT3 := "DFF4945E0336DF4C1C56BC700EFF837F";