4.6.1 Mathematische Grundlagen Die Basiseinheit für Berechnungen im AES stellt das Byte dar, daher sind viele Operationen im AES im GF(2 8 ) definiert. Um den Wert eines Byte darzustellen benutzen wir entweder die Binärzahl-, die Hexadezimalzahloder die Polynomrepräsentation. Betrachten wir die Polynomrepräsentation eines Bytes, so benutzen wir im AES das irreduzible Polynom m(x) = x 8 + x 4 + x 3 + x + 1. Zur Erinnerung: Die Addition entspricht dem Bitweisen xor, bzw. dem xor der korrespondierenden Koeffizienten der Polynome. Die Multiplikation entspricht der Polynommultiplikation modulo m(x). Die Multiplikation kann mit Hilfe der iterierten Multiplikation eines Polynoms mit x und dem bedingten Subtrahieren (bzw. Addieren) von m(x)) implementiert werden. Auf dem Bitlevel bedeutet dieses: Führe einen Linksshift aus. Erhalten wir einen Überlauf, so xor-e das Resultat mit 100011011. Übernehme nur die hinteren 8 Bits. Diese Operation nennen wir xtime(). 178
4.6.1 Mathematische Grundlagen Die Basiseinheit für Berechnungen im AES stellt das Byte dar, daher sind viele Operationen im AES im GF(2 8 ) definiert. Um den Wert eines Byte darzustellen benutzen wir entweder die Binärzahl-, die Hexadezimalzahloder die Polynomrepräsentation. Betrachten wir die Polynomrepräsentation eines Bytes, so benutzen wir im AES das irreduzible Polynom m(x) = x 8 + x 4 + x 3 + x + 1. Zur Erinnerung: Die Addition entspricht dem Bitweisen xor, bzw. dem xor der korrespondierenden Koeffizienten der Polynome. Die Multiplikation entspricht der Polynommultiplikation modulo m(x). Die Multiplikation kann mit Hilfe der iterierten Multiplikation eines Polynoms mit x und dem bedingten Subtrahieren (bzw. Addieren) von m(x)) implementiert werden. Auf dem Bitlevel bedeutet dieses: Führe einen Linksshift aus. Erhalten wir einen Überlauf, so xor-e das Resultat mit 100011011. Übernehme nur die hinteren 8 Bits. Diese Operation nennen wir xtime(). 178
4.6.1 Mathematische Grundlagen Die Basiseinheit für Berechnungen im AES stellt das Byte dar, daher sind viele Operationen im AES im GF(2 8 ) definiert. Um den Wert eines Byte darzustellen benutzen wir entweder die Binärzahl-, die Hexadezimalzahloder die Polynomrepräsentation. Betrachten wir die Polynomrepräsentation eines Bytes, so benutzen wir im AES das irreduzible Polynom m(x) = x 8 + x 4 + x 3 + x + 1. Zur Erinnerung: Die Addition entspricht dem Bitweisen xor, bzw. dem xor der korrespondierenden Koeffizienten der Polynome. Die Multiplikation entspricht der Polynommultiplikation modulo m(x). Die Multiplikation kann mit Hilfe der iterierten Multiplikation eines Polynoms mit x und dem bedingten Subtrahieren (bzw. Addieren) von m(x)) implementiert werden. Auf dem Bitlevel bedeutet dieses: Führe einen Linksshift aus. Erhalten wir einen Überlauf, so xor-e das Resultat mit 100011011. Übernehme nur die hinteren 8 Bits. Diese Operation nennen wir xtime(). 178
4.6.1 Mathematische Grundlagen Die Basiseinheit für Berechnungen im AES stellt das Byte dar, daher sind viele Operationen im AES im GF(2 8 ) definiert. Um den Wert eines Byte darzustellen benutzen wir entweder die Binärzahl-, die Hexadezimalzahloder die Polynomrepräsentation. Betrachten wir die Polynomrepräsentation eines Bytes, so benutzen wir im AES das irreduzible Polynom m(x) = x 8 + x 4 + x 3 + x + 1. Zur Erinnerung: Die Addition entspricht dem Bitweisen xor, bzw. dem xor der korrespondierenden Koeffizienten der Polynome. Die Multiplikation entspricht der Polynommultiplikation modulo m(x). Die Multiplikation kann mit Hilfe der iterierten Multiplikation eines Polynoms mit x und dem bedingten Subtrahieren (bzw. Addieren) von m(x)) implementiert werden. Auf dem Bitlevel bedeutet dieses: Führe einen Linksshift aus. Erhalten wir einen Überlauf, so xor-e das Resultat mit 100011011. Übernehme nur die hinteren 8 Bits. Diese Operation nennen wir xtime(). 178
Beispiel für die Addition: 10011100 2 11000111 2 = 01011011 2 oder äquivalent (x 7 +x 4 +x 3 +x 2 ) (x 7 +x 6 +x 2 +x 1 +1) = x 6 +x 4 +x 3 +x 1 +1. Beispiel für die Multiplikation: (x 6 + x 4 + x 2 + x + 1) (x 7 + x + 1) = x 13 + x 11 + x 9 + x 8 + 2 x 7 + x 6 + x 5 + x 4 + x 3 + 2 x 2 + 2 x + 1 = x 13 + x 11 + x 9 + x 8 + x 6 + x 5 + x 4 + x 3 + 1 (x 13 + x 11 + x 9 + x 8 + x 6 + x 5 + x 4 + x 3 + 1) (x 5 m(x)) (x 11 + x 4 + x 3 + 1) (x 3 m(x)) x 7 + x 6 + 1 mod m(x). Beispiel für xtime(): xtime(x 7 + 1) = 100000010 2 100011011 2 = 00011001 2 x 4 + x 3 + 1. 179
Beispiel für die Addition: 10011100 2 11000111 2 = 01011011 2 oder äquivalent (x 7 +x 4 +x 3 +x 2 ) (x 7 +x 6 +x 2 +x 1 +1) = x 6 +x 4 +x 3 +x 1 +1. Beispiel für die Multiplikation: (x 6 + x 4 + x 2 + x + 1) (x 7 + x + 1) = x 13 + x 11 + x 9 + x 8 + 2 x 7 + x 6 + x 5 + x 4 + x 3 + 2 x 2 + 2 x + 1 = x 13 + x 11 + x 9 + x 8 + x 6 + x 5 + x 4 + x 3 + 1 (x 13 + x 11 + x 9 + x 8 + x 6 + x 5 + x 4 + x 3 + 1) (x 5 m(x)) (x 11 + x 4 + x 3 + 1) (x 3 m(x)) x 7 + x 6 + 1 mod m(x). Beispiel für xtime(): xtime(x 7 + 1) = 100000010 2 100011011 2 = 00011001 2 x 4 + x 3 + 1. 179
Beispiel für die Addition: 10011100 2 11000111 2 = 01011011 2 oder äquivalent (x 7 +x 4 +x 3 +x 2 ) (x 7 +x 6 +x 2 +x 1 +1) = x 6 +x 4 +x 3 +x 1 +1. Beispiel für die Multiplikation: (x 6 + x 4 + x 2 + x + 1) (x 7 + x + 1) = x 13 + x 11 + x 9 + x 8 + 2 x 7 + x 6 + x 5 + x 4 + x 3 + 2 x 2 + 2 x + 1 = x 13 + x 11 + x 9 + x 8 + x 6 + x 5 + x 4 + x 3 + 1 (x 13 + x 11 + x 9 + x 8 + x 6 + x 5 + x 4 + x 3 + 1) (x 5 m(x)) (x 11 + x 4 + x 3 + 1) (x 3 m(x)) x 7 + x 6 + 1 mod m(x). Beispiel für xtime(): xtime(x 7 + 1) = 100000010 2 100011011 2 = 00011001 2 x 4 + x 3 + 1. 179
Beispiel für die Addition: 10011100 2 11000111 2 = 01011011 2 oder äquivalent (x 7 +x 4 +x 3 +x 2 ) (x 7 +x 6 +x 2 +x 1 +1) = x 6 +x 4 +x 3 +x 1 +1. Beispiel für die Multiplikation: (x 6 + x 4 + x 2 + x + 1) (x 7 + x + 1) = x 13 + x 11 + x 9 + x 8 + 2 x 7 + x 6 + x 5 + x 4 + x 3 + 2 x 2 + 2 x + 1 = x 13 + x 11 + x 9 + x 8 + x 6 + x 5 + x 4 + x 3 + 1 (x 13 + x 11 + x 9 + x 8 + x 6 + x 5 + x 4 + x 3 + 1) (x 5 m(x)) (x 11 + x 4 + x 3 + 1) (x 3 m(x)) x 7 + x 6 + 1 mod m(x). Beispiel für xtime(): xtime(x 7 + 1) = 100000010 2 100011011 2 = 00011001 2 x 4 + x 3 + 1. 179
180 Andreas Jakoby Das multiplikative Inverse p 1 (x) zu einem Polynom p(x), d.h. p(x) p 1 (x) 1 mod m(x) können wir mit Hilfe des erweiterten Algorithmus von Euklid bestimmen. Mit Hilfe dieses Verfahrens können wir für zwei Polynome p(x) und m(x) zwei Polynome p(x) und m(x) bestimmen, so dass ist. Wir erhalten somit p(x) p(x) + m(x) m(x) = 1 p 1 (x) = p(x) mod m(x).
180 Andreas Jakoby Das multiplikative Inverse p 1 (x) zu einem Polynom p(x), d.h. p(x) p 1 (x) 1 mod m(x) können wir mit Hilfe des erweiterten Algorithmus von Euklid bestimmen. Mit Hilfe dieses Verfahrens können wir für zwei Polynome p(x) und m(x) zwei Polynome p(x) und m(x) bestimmen, so dass ist. Wir erhalten somit p(x) p(x) + m(x) m(x) = 1 p 1 (x) = p(x) mod m(x).
181 Andreas Jakoby Darstellung von Bytes: Ist b 7 b 6... b 0 die Darstellung eines Bytes in Binärdarstellung, dann erhalten wir die Polynomdarstellung über (b 7 b 6... b 0 ) 2 = b 7 x 7 +b 6 x 6 +b 5 x 5 +b 4 x 4 +b 3 x 3 +b 2 x 2 +b 1 x+b 0. Um die Binärdarstellung in Hexadezimal Darstellung umzuwandeln, benutzen wir für b 7 b 6 b 5 b 4 und b 3 b 2 b 1 b 0 die folgende Tabelle 0000 2 = 0 16 0001 2 = 1 16 0010 2 = 2 16 0011 2 = 3 16 0100 2 = 4 16 0101 2 = 5 16 0110 2 = 6 16 0111 2 = 7 16 1000 2 = 8 16 1001 2 = 9 16 1010 2 = A 16 1011 2 = B 16 1100 2 = C 16 1101 2 = D 16 1110 2 = E 16 1111 2 = F 16
182 Andreas Jakoby Polynome mit Koeffizienten in GF(2 8 ) Verschiedene Operationen im AES können wir mit Hilfe von Addition und Multiplikation von Polynomen vom Grad 3 darstellen. Die Koeffizienten dieser Polynome stellen wiederum Elemente endlicher Körpern (GF(2 8 )) dar. Die Polynome selbst, bilden jedoch keinen endlichen Körper. Sei a(x) = a 3 x 3 + a 2 x 2 + a 1 x + a 0 ein solches Polynom, dann benutzen wir auch die Schreibweise [a 0, a 1, a 2, a 3 ].
Seien a(x) = a 3 x 3 + a 2 x 2 + a 1 x + a 0 b(x) = b 3 x 3 + b 2 x 2 + b 1 x + b 0 zwei solche Polynome, dann erhalten wir Addition + über a(x)+b(x) = (a 3 b 3 ) x 3 +(a 2 b 2 ) x 2 +(a 1 b 1 ) x +(a 0 b 0 ). Multiplikation über die Polynommultiplikation modulo x 4 + 1. 183
184 Andreas Jakoby Es gilt x i mod (x 4 + 1) = x i mod 4 somit können wir die Multiplikation wie folgt vereinfachen: Sei d(x) = d 3 x 3 + d 2 x 2 + d 1 x + d 0 = a(x) b(x) dann erhalten wir d 0 d 1 d 2 = d 3 a 0 a 3 a 2 a 1 a 1 a 0 a 3 a 2 a 2 a 1 a 0 a 3 a 3 a 2 a 1 a 0 b 0 b 1 b 2 b 3.
184 Andreas Jakoby Es gilt x i mod (x 4 + 1) = x i mod 4 somit können wir die Multiplikation wie folgt vereinfachen: Sei d(x) = d 3 x 3 + d 2 x 2 + d 1 x + d 0 = a(x) b(x) dann erhalten wir d 0 d 1 d 2 = d 3 a 0 a 3 a 2 a 1 a 1 a 0 a 3 a 2 a 2 a 1 a 0 a 3 a 3 a 2 a 1 a 0 b 0 b 1 b 2 b 3.
185 Andreas Jakoby Die Multiplikation mit einem festen Polynom a(x) ist nicht für alle Polynome a(x) invertierbar. Im AES wir jedoch ein Polynom benutzt welches ein multiplikatives Inverses besitzt: Wählen wir a(x) = 03 16 x 3 + 01 16 x 2 + 01 16 x + 02 16 a 1 (x) = 0B 16 x 3 + 0D 16 x 2 + 09 16 x + 0E 16. a(x) = 01 16 x 3, d.h. a 3 = 01 16 und a 2 = a 1 = a 0 = 00 16, dann erhalten wir über die Operation eine Rotation nach links: [00 16, 00 16, 00 16, 01 16 ] [b 0, b 1, b 2, b 3 ] = [b 1, b 2, b 3, b 0 ].
4.6.2 Zustand des AES Die Basiseinheit für Berechnungen im AES stellt das Byte dar. Sei a 0... a 7 die folge der Bits im Speicher, dann benutzen wir die Darstellungen (a 7... a 0 ) 2 und a 7 x 7 +... + a 1 x + a 0. Die Blocklänge im AES beträgt 128 Bits, d.h. 16 Byte. Abhängig vom Grad der Sicherheit, benutzt das AES Schlüssel der Länge 128, 192 oder 256 Bit, bzw. 16, 24 oder 32 Byte. Ist x ein Block bestehend aus n Bytes, dann bezeichnen wir im Folgenden mit x[i] das i-te Byte. 1 1 Allgemein bezeichnen wir mit x[i] das i-te Element in der Zeichenkette x. An anderer Stelle beziehen wir uns hierbei oft auf ein Bit. Bei der nun folgenden Beschreibung des AES bezeichnet dieses jedoch ein Byte. 186
187 Andreas Jakoby Den Zustand des AES können wir Byteweise mit Hilfe eines 4 4-Arrays beschreiben: Input in 0 in 4 in 8 in 12 in 1 in 5 in 9 in 13 in 2 in 6 in 10 in 14 in 3 in 7 in 11 in 15 Zustand s 0,0 s 0,1 s 0,2 s 0,3 s 1,0 s 1,1 s 1,2 s 1,3 s 2,0 s 2,1 s 2,2 s 2,3 s 3,0 s 3,1 s 3,2 s 3,3 Output out 0 out 4 out 8 out 12 out 1 out 5 out 9 out 13 out 2 out 6 out 10 out 14 out 3 out 7 out 11 out 15 Die Funktion Square: ({0, 1} 8 ) 16 ({0, 1} 8 ) 4 4 wandelt ein 1-dimensionales Feld aus 16 Bytes in ein 2-dimensionales 4 4-Matrix um. Sei s = (s ) [0..3] = Square(x) für x ({0, 1} 8 ) 16, dann gilt für alle i, j [0..3] s = x[i + 4 j].
Die Funktion InvSquare: ({0, 1} 8 ) 4 4 ({0, 1} 8 ) 16 gibt die Umkehrfunktion von Square() an, d.h. für gilt x = InvSquare(s) x[i + 4 j] = s. Sei s = (s ) [0..3] und s = (s ) [0..3], dann definieren wir s s = (s s ) [0..3] als die elementweise Addition 2 in GF(2 8 ) der Matrizen. 2 bitweises xor 188
4.6.3 Unterfunktionen des AES Die einzelnen Verschlüsselungsschritte des AES lassen sich mit Hilfe von 4 individuellen Unterfunktionen und deren Umkehrfunktionen aufbauen: AddRoundKey() und InvAddRoundKey() ShiftRows() und InvShiftRows() MixColumns() und InvMixColumns() SubBytes() und InvSubBytes() 189
AddRoundKey() und InvAddRoundKey(): Bei AddRoundKey() sind Funktion und Umkehrfunktion identisch: Eingabe: eine 4 4-Byte-Matrix s und ein 16-Byte Rundenschlüssel K i Ausgabe: die 4 4-Byte-Matrix s Square(K i ). Die einzelnen Rundenschlüssel K 0,..., K r 1 werden mit Hilfe der Funktion KeyExpansion aus dem Schlüssel K generiert. Die 4 4-Byte-Matrix s gibt den aktuellen Zustand des Rundentextes an. 190
191 Andreas Jakoby K i [0] K i [1] K i [2] K i [3] K i [4] K i [5] K i [6] K i [7] K i [8] K i [9] K i [10] K i [11] K i [12] K i [13] K i [14] K i [15] s 0,0 s 0,1 s 0,2 s 0,3 s 0,0 s 0,1 s 0,2 s 0,3 s 1,0 s 1,1 s 1,2 s 1,3 s 1,0 s 1,1 s 1,2 s 1,3 s 2,0 s 2,1 s 2,2 s 2,3 s s 2,0 s 2,1 2,2 s 2,3 s 3,0 s 3,1 s 3,2 s 3,3 s 3,0 s 3,1 s 3,2 s 3,3
ShiftRows() und InvShiftRows(): ShiftRows() führt einen zyklischen Shift auf die einzelnen Zeilen einer 4 4-Byte-Matrix aus. Hierbei wird die i-te Zeile um i Positionen geshifted. Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit s = s i,(j+i) mod 4. Für die Umkehrfunktion InvShiftRows() erhalten wir: Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit s i,(j+i) mod 4 = s. 192
ShiftRows() und InvShiftRows(): ShiftRows() führt einen zyklischen Shift auf die einzelnen Zeilen einer 4 4-Byte-Matrix aus. Hierbei wird die i-te Zeile um i Positionen geshifted. Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit s = s i,(j+i) mod 4. Für die Umkehrfunktion InvShiftRows() erhalten wir: Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit s i,(j+i) mod 4 = s. 192
193 Andreas Jakoby ShiftRows() s 0,0 s 0,1 s 0,2 s 0,3 s 0,0 s 0,1 s 0,2 s 0,3 s 1,0 s 1,1 s 1,2 s 1,3 s 1,0 s 1,1 s 1,2 s 1,3 s 2,0 s 2,1 s 2,2 s 2,3 s 2,0 s 2,1 s 2,2 s 2,3 s 3,0 s 3,1 s 3,2 s 3,3 s 3,0 s 3,1 s 3,2 s 3,3
MixColumns() und InvMixColumns(): MixColumns() interpretiert jede Spalte der 4 4-Byte-Matrix als ein Polynom s j = s 3,j x 3 + s 2,j + s 1,j + s 0,j mit Koeffizienten aus GF(2 8 ) und Multipliziert dieses mit dem Polynom p(x) = 03 16 x 3 + 02 16 x 2 + 01 16 x + 01 16 Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit 0 1 0 s 0,j B s 1,j C @ s 2,j A = B @ s 3,j 02 16 03 16 01 16 01 16 01 16 02 16 03 16 01 16 01 16 01 16 02 16 03 16 03 16 01 16 01 16 02 16 1 C A 0 B @ bzw. s 0,j := (02 16 s 0,j ) (03 16 s 1,j ) s 2,j s 3,j s 1,j := (02 16 s 1,j ) (03 16 s 2,j ) s 3,j s 0,j s 2,j := (02 16 s 2,j ) (03 16 s 3,j ) s 0,j s 1,j s 0,j s 1,j s 2,j s 3,j 1 C A für alle j [0..3]. s 3,j := (02 16 s 3,j ) (03 16 s 0,j ) s 1,j s 2,j 194
Die Umkehrfunktion InvMixColumns() erhalten wir über die Multipliziert des Spalten-Polynoms mit p 1 (x) = 0B 16 x 3 + 0D 16 x 2 + 09 16 x + 0E 16 Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit 0 1 0 s 0,j B s 1,j C @ s 2,j A = B @ s 3,j bzw. 0E 16 0B 16 0D 16 09 16 09 16 0E 16 0B 16 0D 16 0D 16 09 16 0E 16 0B 16 0B 16 0D 16 09 16 0E 16 1 C A 0 B @ s 0,j s 1,j s 2,j s 3,j s 0,j := (0E 16 s 0,j ) (0B 16 s 1,j ) (0D 16 s 2,j ) (09 16 s 3,j ) s 1,j := (0E 16 s 1,j ) (0B 16 s 2,j ) (0D 16 s 3,j ) (09 16 s 0,j ) s 2,j := (0E 16 s 2,j ) (0B 16 s 3,j ) (0D 16 s 0,j ) (09 16 s 1,j ) s 3,j := (0E 16 s 3,j ) (0B 16 s 0,j ) (0D 16 s 1,j ) (09 16 s 2,j ) 1 C A für alle j [0..3]. 195
196 Andreas Jakoby p(x) s j (x) s 0,0 s 0,1 s 0,2 s 0,3 s 0,0 s 0,1 s 0,2 s 0,3 s 1,0 s 1,1 s 1,2 s 1,3 s 1,0 s 1,1 s 1,2 s 1,3 s 2,0 s 2,1 s 2,2 s 2,3 s 2,0 s 2,1 s 2,2 s 2,3 s 3,0 s 3,1 s 3,2 s 3,3 s 3,0 s 3,1 s 3,2 s 3,3
SubBytes() und InvSubBytes(): SubBytes() ist eine elementweise Transformation einer 4 4-Byte-Matrix mit Hilfe einer nicht-linearen invertierbaren S-Box. Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit s = Eintrag in der u-ten Zeile und v-ten Spalte der S-Box Tabelle wobei s = uv mit u, v {0, 1} 4 ist. Für die Umkehrfunktion InvSubBytes() erhalten wir: Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit s = Eintrag in der u-ten Zeile und v-ten Spalte der inversen S-Box Tabelle wobei s = uv mit u, v {0, 1} 4 ist. Die Tabellen für die S-Box und für die inversen S-Box befinden sich auf den nächsten beiden Folien. 197
SubBytes() und InvSubBytes(): SubBytes() ist eine elementweise Transformation einer 4 4-Byte-Matrix mit Hilfe einer nicht-linearen invertierbaren S-Box. Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit s = Eintrag in der u-ten Zeile und v-ten Spalte der S-Box Tabelle wobei s = uv mit u, v {0, 1} 4 ist. Für die Umkehrfunktion InvSubBytes() erhalten wir: Eingabe: eine 4 4-Byte-Matrix s. Ausgabe: die 4 4-Byte-Matrix s mit s = Eintrag in der u-ten Zeile und v-ten Spalte der inversen S-Box Tabelle wobei s = uv mit u, v {0, 1} 4 ist. Die Tabellen für die S-Box und für die inversen S-Box befinden sich auf den nächsten beiden Folien. 197
198 Andreas Jakoby S-Box 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 63 7C 77 7B F2 6B 6F C5 30 01 67 2B FE D7 AB 76 1 CA 82 C9 7D FA 59 47 F0 AD D4 A2 AF 9C A4 72 C0 2 B7 FD 93 26 36 3F F7 CC 34 A5 E5 F1 71 D8 31 15 3 04 C7 23 C3 18 96 05 9A 07 12 80 E2 EB 27 B2 75 4 09 83 2C 1A 1B 6E 5A A0 52 3B D6 B3 29 E3 2F 84 5 53 D1 00 ED 20 FC B1 5B 6A CB BE 39 4A 4C 58 CF 6 D0 EF AA FB 43 4D 33 85 45 F9 02 7F 50 3C 9F A8 7 51 A3 40 8F 92 9D 38 F5 BC B6 DA 21 10 FF F3 D2 8 CD 0C 13 EC 5F 97 44 17 C4 A7 7E 3D 64 5D 19 73 9 60 81 4F DC 22 2A 90 88 46 EE B8 14 DE 5E 0B DB A E0 32 3A 0A 49 06 24 5C C2 D3 AC 62 91 95 E4 79 B E7 C8 37 6D 8D D5 4E A9 6C 56 F4 EA 65 7A AE 08 C BA 78 25 2E 1C A6 B4 C6 E8 DD 74 1F 4B BD 8B 8A D 70 3E B5 66 48 03 F6 0E 61 35 57 B9 86 C1 1D 9E E E1 F8 98 11 69 D9 8E 94 9B 1E 87 E9 CE 55 28 DF F 8C A1 89 0D BF E6 42 68 41 99 2D 0F B0 54 BB 16
199 Andreas Jakoby Inverse S-Box 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 52 09 6A D5 30 36 A5 38 BF 40 A3 9E 81 F3 D7 FB 1 7C E3 39 82 9B 2F FF 87 34 8E 43 44 C4 DE E9 CB 2 54 7B 94 32 A6 C2 23 3D EE 4C 95 0B 42 FA C3 4E 3 08 2E A1 66 28 D9 24 B2 76 5B A2 49 6D 8B D1 25 4 72 F8 F6 64 86 68 98 16 D4 A4 5C CC 5D 65 B6 92 5 6C 70 48 50 FD ED B9 DA 5E 15 46 57 A7 8D 9D 84 6 90 D8 AB 00 8C BC D3 0A F7 E4 58 05 B8 B3 45 06 7 D0 2C 1E 8F CA 3F 0F 02 C1 AF BD 03 01 13 8A 6B 8 3A 91 11 41 4F 67 DC EA 97 F2 CF CE F0 B4 E6 73 9 96 AC 74 22 E7 AD 35 85 E2 F9 37 E8 1C 75 DF 6E A 47 F1 1A 71 1D 29 C5 89 6F B7 62 0E AA 18 BE 1B B FC 56 3E 4B C6 D2 79 20 9A DB C0 FE 78 CD 5A F4 C 1F DD A8 33 88 07 C7 31 B1 12 10 59 27 80 EC 5F D 60 51 7F A9 19 B5 4A 0D 2D E5 7A 9F 93 C9 9C EF E A0 E0 3B 4D AE 2A F5 B0 C8 EB BB 3C 83 53 99 61 F 17 2B 04 7E BA 77 D6 26 E1 69 14 63 55 21 0C 7D
200 Andreas Jakoby S-Box s 0,0 s 0,1 s 0,2 s 0,3 s 0,0 s 0,1 s 0,2 s 0,3 s 1,0 s 1,1 s 1,2 s 1,3 s 1,0 s 1,1 s 1,2 s 1,3 s 2,0 s 2,1 s 2,2 s 2,3 s 2,0 s 2,1 s 2,2 s 2,3 s 3,0 s 3,1 s 3,2 s 3,3 s 3,0 s 3,1 s 3,2 s 3,3
201 Andreas Jakoby Bemerkungen zur Konstruktion der S-Box: Sei s ein Byte, welches wir mit Hilfe der S-Box transformieren wollen, dann verfahren wir wie folgt: Bestimme das multiplikative Inverse s 1 von s in GF(2 8 ). Für s = 00 wählen wir s 1 = 00. Seien s 1 [i] die Bits von s 1, d.h. s 1 = s 1 [7]s 1 [6]s 1 [5]s 1 [4]s 1 [3]s 1 [2]s 1 [1]s 1 [0] dann erhalten wir die Bits des Ergebnisses über s = s [7]s [6]s [5]s [4]s [3]s [2]s [1]s [0] s [i] = s 1 [i] s 1 [i + 4 mod 8] s 1 [i + 5 mod 8] s 1 [i + 6 mod 8] s 1 [i + 7 mod 8] c[i] wobei c = c[7]c[6]c[5]c[4]c[3]c[2]c[1]c[0] = 01100011 2 ist.
202 Andreas Jakoby Alternativ können wir die Tabelleneinträge auch über die folgende affin-lineare Transfromation aus dem multiplikative Inverse s 1 von s bestimmen: 0 s 1 0 1 0 1 [0] 1 0 0 0 1 1 1 1 s 1 [0] 0 1 1 s [1] 1 1 0 0 0 1 1 1 s 1 [1] s [2] 1 1 1 0 0 0 1 1 s 1 s [3] [2] 1 s [4] = 1 1 1 1 0 0 0 1 s 1 [3] 0 1 1 1 1 1 0 0 0 s 1 + 0 B s [5] [4] C B 0 1 1 1 1 1 0 0 C s @ s [6] A @ 0 0 1 1 1 1 1 0 A B 1 0 [5] @ s 1 C B 1 C s [7] [6] A @ 1 A 0 0 0 1 1 1 1 1 0 s 1 [7]
4.6.4 Die Rundenschlüssel Um den Rundenschlüssel zu bestimmen benötigen wir noch einige einfache Hilfsfunktionen, die auf einem 4-Byte Wort w = w[0]w[1]w[2]w[3] arbeiten: RotWord() führt einen zyklischen Shift um ein Byte nach links aus: RotWord(w[0]w[1]w[2]w[3]) = w[1]w[2]w[3]w[0]. SubWord() wendet einen S-Box-Operation auf jedes Byte an: SubWord(w[0]w[1]w[2]w[3]) = S(w[0])S(w[1])S(w[2])S(w[3]). Rcon(i) für i N mit i > 0 ist Rcon(i) = c i 00 16 00 16 00 16, wobei wir die Rundenkonstante c i wie folgt über die Operationen in GF(2 8 ) und der Polynomdarstellung bestimmen c i = x i 1 (modm(x)). 203
Algorithmus KeyExpansion(K) Eingabe: 4 k-byte Schlüssel K Ergebnis: Folge der Rundenschlüssel (K 0,..., K l ) 1: l := 6 + k 2: for i = 0 to k 1 do h i := K[4i]K[4i + 1]K[4i + 2]K[4i + 3] end for 3: for i = k to 4 l do 4: t := h i 1 5: if (i mod k) = 0 then 6: t := SubWord(RotWord(t)) Rcon(i/k) 7: else 8: if k = 8 (i mod k) = 4 then t := SubWord(t) end if 9: end if 10: h i := h i k t 11: end for 12: for i = 0 to l do K i := h 4i h 4i+1 h 4i+2 h 4i+3 end for 13: Return((K 0,..., K l )) 204
Algorithmus KeyExpansion(K) Eingabe: 4 k-byte Schlüssel K Ergebnis: Folge der Rundenschlüssel (K 0,..., K l ) 1: l := 6 + k 2: for i = 0 to k 1 do h i := K[4i]K[4i + 1]K[4i + 2]K[4i + 3] end for 3: for i = k to 4 l do 4: t := h i 1 5: if (i mod k) = 0 then 6: t := SubWord(RotWord(t)) Rcon(i/k) 7: else 8: if k = 8 (i mod k) = 4 then t := SubWord(t) end if 9: end if 10: h i := h i k t 11: end for 12: for i = 0 to l do K i := h 4i h 4i+1 h 4i+2 h 4i+3 end for 13: Return((K 0,..., K l )) 204
Algorithmus KeyExpansion(K) Eingabe: 4 k-byte Schlüssel K Ergebnis: Folge der Rundenschlüssel (K 0,..., K l ) 1: l := 6 + k 2: for i = 0 to k 1 do h i := K[4i]K[4i + 1]K[4i + 2]K[4i + 3] end for 3: for i = k to 4 l do 4: t := h i 1 5: if (i mod k) = 0 then 6: t := SubWord(RotWord(t)) Rcon(i/k) 7: else 8: if k = 8 (i mod k) = 4 then t := SubWord(t) end if 9: end if 10: h i := h i k t 11: end for 12: for i = 0 to l do K i := h 4i h 4i+1 h 4i+2 h 4i+3 end for 13: Return((K 0,..., K l )) 204
Algorithmus KeyExpansion(K) Eingabe: 4 k-byte Schlüssel K Ergebnis: Folge der Rundenschlüssel (K 0,..., K l ) 1: l := 6 + k 2: for i = 0 to k 1 do h i := K[4i]K[4i + 1]K[4i + 2]K[4i + 3] end for 3: for i = k to 4 l do 4: t := h i 1 5: if (i mod k) = 0 then 6: t := SubWord(RotWord(t)) Rcon(i/k) 7: else 8: if k = 8 (i mod k) = 4 then t := SubWord(t) end if 9: end if 10: h i := h i k t 11: end for 12: for i = 0 to l do K i := h 4i h 4i+1 h 4i+2 h 4i+3 end for 13: Return((K 0,..., K l )) 204
205 Andreas Jakoby Illustration von KeyExpansion(K) bei einer Schlüssellänge von 16 Byte bzw. 128 Bit, d.h. k = 4. h 0 h 1 h 2 h 3 h 4 h 5 h 6 h 7 h 8 RotWord() RotWord() SubWord() SubWord() Rcon(1) Rcon(2)
206 Andreas Jakoby Illustration von KeyExpansion(K) bei einer Schlüssellänge von 24 Byte bzw. 192 Bit, d.h. k = 6. h 0 h 1 h 2 h 3 h 4 h 5 h 6 h 7 h 8 h 9 h 10 h 11 h 12 RotWord() RotWord() SubWord() SubWord() Rcon(1) Rcon(2)
207 Andreas Jakoby Illustration von KeyExpansion(K) bei einer Schlüssellänge von 32 Byte bzw. 256 Bit, d.h. k = 8. h 0 h 1 h 2 h 3 h 4 h 5 h 6 h 7 h 8 h 9 h 10 h 11 h 12 h 13 h 14 h 15 h 16 RotWord() RotWord() SubWord() SubWord() SubWord() Rcon(1) Rcon(2)
4.6.5 Der AES-Algorithmus Der AES-Algorithmus verschlüsselt einen Plaintext von 16 Byte in mehreren Runden. Die Anzahl der Runden hängt hierbei von der Schlüssellänge ab. Es gilt: bei 16-Byte Schlüssel beträgt die Rundenzahl 10, bei 24-Byte Schlüssel beträgt die Rundenzahl 12 und bei 32-Byte Schlüssel beträgt die Rundenzahl 14. Die Beschreibung von AES in Federal Infomation Processing Standards Publication 197 erlaubt auch die Benutzung größerer Blöcke und Schlüssel. Auf die hierbei benötigten relativ einfachen Modifikationen werden wir jedoch nicht eingehen. 208
209 Andreas Jakoby Algorithmus AES-Verschlüsselung(x, K) Eingabe: 16-Byte Plaintext x und 4 k-byte Schlüssel K Ergebnis: 16-Byte Ciphertext y 1: (K 0,..., K l ) :=KeyExpansion(K) 2: s :=Square(x) 3: s :=AddRoundKey(s, K 0 ) 4: for i = 1 to l 1 by +1 do 5: s :=SubBytes(s) 6: s :=ShiftRows(s) 7: s :=MixColumns(s) 8: s :=AddRoundKey(s, K i ) 9: end for 10: s :=SubBytes(s) 11: s :=ShiftRows(s) 12: s :=AddRoundKey(s, K l ) 13: Return(InvSquare(s))
210 Andreas Jakoby Algorithmus AES-Entschlüsselung(y, K) Eingabe: 16-Byte Ciphertext y und 4 k-byte Schlüssel K Ergebnis: 16-Byte Ciphertext x 1: (K 0,..., K l ) :=KeyExpansion(K) 2: s :=Square(y) 3: s :=AddRoundKey(s, K l ) 4: for i = l 1 to 1 by 1 do 5: s :=InvShiftRows(s) 6: s :=InvSubBytes(s) 7: s :=AddRoundKey(s, K i ) 8: s :=InvMixColumns(s) 9: end for 10: s :=InvShiftRows(s) 11: s :=InvSubBytes(s) 12: s :=AddRoundKey(s, K l ) 13: Return(InvSquare(s))