Einzelnen Beitrag anzeigen

qwertz543221
(Gast)

n/a Beiträge
 
#6

AW: Advanced Encryption Standard 128 bit Eigenimplementierung - key schedule

  Alt 29. Dez 2012, 22:01
Könnte jemand testvektoren für aes 128 (text,key,chiffre) zur überprüfung angeben?

ich habe jetzt den algorithmus in zwei unterschiedlichen programmen(einmal gesondert in einer unit, und einmal mit anderen algorithmen zusammen) und habe bei beiden differente ausgaben.

kann es an der klassendefinition und den jeweiligen zugriffsrechten zusammenhängen?

hier sind zwei ausgabebeispiele bei gleichem input:

BenutzerSchlüssel: test01af5
Eingabe: Testvektor
Ausgabe 1: cLffabrarTFxNvtjTNYDHG (base64)
Ausgabe 2: dnwm0e+gYhWhRaVn1X2GX0 (~)

anbei der quelltext für ausgabe 1

Delphi-Quellcode:
Unit Mainprogram;

Interface

Uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, StdCtrls, Crypto, ExtCtrls,Advanced_Encryption_Standard;

Type


  TForm1 = Class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    LabeledEdit1: TLabeledEdit;
    Button2: TButton;
    Procedure Button1Click(Sender: TObject);
    Procedure Button2Click(Sender: TObject);

  Private

  Public
    { Public declarations }
  End;

Var
  Form1: TForm1;
  Aes: Taes;
  Data: Tdata; //datenverarbeitung und ausgabe


Implementation

{$R *.dfm}


Procedure TForm1.Button1Click(Sender: TObject);
Var
  Text, Key: String;

Begin
  Text := Memo1.Text;

  Key := Labelededit1.Text;
  Text := Aes.Aes_text(Text, Key, Aes.Keysize128, 0);
  Text := Data.Base64(Text, 0); // Text := Data.Str_tohex(Text, Length(Text));
  Memo1.Text := Text;
End;

Procedure TForm1.Button2Click(Sender: TObject);
Var
  Text, Key: String;

Begin
  Text := Memo1.Text;
  Key := Labelededit1.Text;
  // Text := Data.Str_fromhex(Text);
  Text := Data.Base64(Text, 1);
  Text := Aes.Aes_text(Text, Key, Aes.Keysize128, 1);
  Memo1.Text := Text;
End;

Initialization

Data := Tdata.Create;
Aes := Taes.Create;

Finalization

Aes.Free;
Data.Free;

End.


Unit Advanced_Encryption_Standard;

Interface

{$RANGECHECKS on}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS on}

Uses
  Messages, SysUtils, Classes, StdCtrls;

Type
  // 128 bit /16 byte /4*4 blocks for 128 bit key
  Trow = Array [1 .. 4] Of Byte;
  Tcolumn = Array [1 .. 4] Of Byte;
  Tstate = Array [1 .. 4] Of Trow;
  Tword = Array [1 .. 4] Of Byte;
  Tinput = Array [1 .. 16] Of Byte; //to fill a custom state

  { expanded key arrays
    128 bit input block =>176 bytes=>11 16 byte blocks
    192 bit input block=>208 bytes=> 8 24 byte bocks
    256 bit input block=>240 bytes=> 7 32 byte blocks }

  Tkey128 = Array [1 .. 176] Of Byte;
  Tkey192 = Array [1 .. 208] Of Byte;
  Tkey256 = Array [1 .. 240] Of Byte;

  Tsubkeys128 = Array [1 .. 11] Of Tstate;

  //counters i,j:=1<= 4
  Taes = Class
    // Public
  Var
    Testroundkey: Tstate;
    //for initalization keyschedule test
    Testexpandedkey128: Tkey128;
    Testcount: Integer;

  Const
    Keysize128 = 128;
    Keysize192 = 192;
    Keysize256 = 256;

    Function Aes_text(Var Text, Key: String; Bitlen: Integer; Mode: Byte): String;

  Private

  Var
    Mixcolstate: Tstate;
    Mixcolinvstate: Tstate;
    Expandedkey128: Tkey128;
    Expandedkey192: Tkey192;
    Expandedkey256: Tkey256;
    Keys: Array Of String;

  Const

    Teststatearray: Tinput = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);

    Sbox: Array [0 .. 255] Of Byte =

    // 0 1 2 3 4 5 6 7 8 9 A B C D E F
      ($63, $7C, $77, $7B, $F2, $6B, $6F, $C5, $30, $01, $67, $2B, $FE, $D7, $AB, $76, //0
      $CA, $82, $C9, $7D, $FA, $59, $47, $F0, $AD, $D4, $A2, $AF, $9C, $A4, $72, $C0, //1
      $B7, $FD, $93, $26, $36, $3F, $F7, $CC, $34, $A5, $E5, $F1, $71, $D8, $31, $15, //2
      $04, $C7, $23, $C3, $18, $96, $05, $9A, $07, $12, $80, $E2, $EB, $27, $B2, $75, //3
      $09, $83, $2C, $1A, $1B, $6E, $5A, $A0, $52, $3B, $D6, $B3, $29, $E3, $2F, $84, //4
      $53, $D1, $00, $ED, $20, $FC, $B1, $5B, $6A, $CB, $BE, $39, $4A, $4C, $58, $CF, //5
      $D0, $EF, $AA, $FB, $43, $4D, $33, $85, $45, $F9, $02, $7F, $50, $3C, $9F, $A8, //6
      $51, $A3, $40, $8F, $92, $9D, $38, $F5, $BC, $B6, $DA, $21, $10, $FF, $F3, $D2, //7
      $CD, $0C, $13, $EC, $5F, $97, $44, $17, $C4, $A7, $7E, $3D, $64, $5D, $19, $73, //8
      $60, $81, $4F, $DC, $22, $2A, $90, $88, $46, $EE, $B8, $14, $DE, $5E, $0B, $DB, //9
      $E0, $32, $3A, $0A, $49, $06, $24, $5C, $C2, $D3, $AC, $62, $91, $95, $E4, $79, //A
      $E7, $C8, $37, $6D, $8D, $D5, $4E, $A9, $6C, $56, $F4, $EA, $65, $7A, $AE, $08, //B
      $BA, $78, $25, $2E, $1C, $A6, $B4, $C6, $E8, $DD, $74, $1F, $4B, $BD, $8B, $8A, //C
      $70, $3E, $B5, $66, $48, $03, $F6, $0E, $61, $35, $57, $B9, $86, $C1, $1D, $9E, //D
      $E1, $F8, $98, $11, $69, $D9, $8E, $94, $9B, $1E, $87, $E9, $CE, $55, $28, $DF, //E
      $8C, $A1, $89, $0D, $BF, $E6, $42, $68, $41, $99, $2D, $0F, $B0, $54, $BB, $16); //F

    Invsbox: Array [0 .. 255] Of Byte =
    // 0 1 2 3 4 5 6 7 8 9 A B C D E F
      ($52, $09, $6A, $D5, $30, $36, $A5, $38, $BF, $40, $A3, $9E, $81, $F3, $D7, $FB, //0
      $7C, $E3, $39, $82, $9B, $2F, $FF, $87, $34, $8E, $43, $44, $C4, $DE, $E9, $CB, //1
      $54, $7B, $94, $32, $A6, $C2, $23, $3D, $EE, $4C, $95, $0B, $42, $FA, $C3, $4E, //2
      $08, $2E, $A1, $66, $28, $D9, $24, $B2, $76, $5B, $A2, $49, $6D, $8B, $D1, $25, //3
      $72, $F8, $F6, $64, $86, $68, $98, $16, $D4, $A4, $5C, $CC, $5D, $65, $B6, $92, //4
      $6C, $70, $48, $50, $FD, $ED, $B9, $DA, $5E, $15, $46, $57, $A7, $8D, $9D, $84, //5
      $90, $D8, $AB, $00, $8C, $BC, $D3, $0A, $F7, $E4, $58, $05, $B8, $B3, $45, $06, //6
      $D0, $2C, $1E, $8F, $CA, $3F, $0F, $02, $C1, $AF, $BD, $03, $01, $13, $8A, $6B, //7
      $3A, $91, $11, $41, $4F, $67, $DC, $EA, $97, $F2, $CF, $CE, $F0, $B4, $E6, $73, //8
      $96, $AC, $74, $22, $E7, $AD, $35, $85, $E2, $F9, $37, $E8, $1C, $75, $DF, $6E, //9
      $47, $F1, $1A, $71, $1D, $29, $C5, $89, $6F, $B7, $62, $0E, $AA, $18, $BE, $1B, //A
      $FC, $56, $3E, $4B, $C6, $D2, $79, $20, $9A, $DB, $C0, $FE, $78, $CD, $5A, $F4, //B
      $1F, $DD, $A8, $33, $88, $07, $C7, $31, $B1, $12, $10, $59, $27, $80, $EC, $5F, //C
      $60, $51, $7F, $A9, $19, $B5, $4A, $0D, $2D, $E5, $7A, $9F, $93, $C9, $9C, $EF, //D
      $A0, $E0, $3B, $4D, $AE, $2A, $F5, $B0, $C8, $EB, $BB, $3C, $83, $53, $99, $61, //E
      $17, $2B, $04, $7E, $BA, $77, $D6, $26, $E1, $69, $14, $63, $55, $21, $0C, $7D); //F

    Procedure Aes128_Keyschedule_test(Var Keys: Array Of String);

    Procedure Keyschedule_core(Var Word: Tword; Iteration: Integer; Mode: Byte);
    Function Multcolumn(Column: Tcolumn; Mode: Byte): Tcolumn;
    Function Galois_mult(A, B: Byte): Byte; //http://en.wikipedia.org/wiki/Rijndael_mix_columns
    Procedure Shiftrows(Var State: Tstate; Mode: Byte);
    Procedure Rotate(Var Value: Tword; Mode: Byte); // rotate(1d 2c 3a 4f) = 2c 3a 4f 1d
    Procedure AddRoundKey(Var State: Tstate; Roundkey: Tstate);
    Function Getsboxvalue(Index: Byte): Byte;
    Function Getinvsboxvalue(Index: Byte): Byte;
    Function Rcon(Index: Byte): Integer;
    Function Expandkey(Key: Tinput; Var Expandedkey: Tkey128): Byte; Overload;
    //result=number of rounds
    Function Generatesubkeys(Expandedkey: Tkey128): Tsubkeys128;
    Function Expandkey(Key: Tinput; Var Expandedkey: Tkey192): Byte; Overload;
    //result=number of rounds
    Function Expandkey(Key: Tinput; Var Expandedkey: Tkey256): Byte; Overload;
    //result=number of rounds

    Procedure Mixcolumns(Var State: Tstate; Mode: Byte);
    Procedure Subbytes(Var State: Tstate; Mode: Byte); Overload;
    Procedure Subbytes(Var Word: Tword)Overload;
    Procedure Showstate(State: Tstate; Memo: Tmemo);
    Function Texttostate(Substr: String): Tstate;
    Function Texttokey(Key: String): Tinput;
    Function Keytostate(Data: Tinput): Tstate;
    Function Statetotext(State: Tstate): String;
    Procedure Aes(Roundcount: Byte; Var State: Tstate; Keys: Tsubkeys128; Mode: Byte);

  End;

Implementation

{ src: http://en.wikipedia.org/wiki/Rijndael_mix_columns: A c# example
  Multiplication in Rijndael's galois field is a little more complicated. The procedure is as follows:

  * Take two eight-bit numbers, a and b, and an eight-bit product p
  * Set the product to zero.
  * Make a copy of a and b, which we will simply call a and b in the rest of this algorithm
  * Run the following loop eight times:
  1. If the low bit of b is set, exclusive or the product p by the value of a
  2. Keep track of whether the high (eighth from left) bit of a is set to one
  3. Rotate a one bit to the left, discarding the high bit, and making the low bit have a value of zero
  4. If a's hi bit had a value of one prior to this rotation, exclusive or a with the hexadecimal number 0x1b
  5. Rotate b one bit to the right, discarding the low bit, and making the high (eighth from left) bit have a value of zero.
  6. The product p now has the product of a and b
}


//------------------------------------------------------------------------------
{
  The Key Schedule is responsible for expanding a short key into a larger key,
  whose parts are used during the different iterations. Each key size is expanded
  to a different size:

  An 128 bit key is expanded to an 176 byte key.
  An 192 bit key is expanded to an 208 byte key.
  An 256 bit key is expanded to an 240 byte key.

  There is a relation between the cipher key size,
  the number of rounds and the ExpandedKey size.
  For an 128-bit key, there is one initial AddRoundKey operation
  plus there are 10 rounds and each rounds need a new 16 byte key,
  therefor we require 10+1 RoundKeys of 16 byte, which equals 176 byte.
  The same logic can be applied to the two other cipher key sizes.
  The general formula is that: ExpandedKeySize = (nbrRounds+1) * BlockSize
  }


Procedure Taes.Aes128_Keyschedule_test(Var Keys: Array Of String);
Var
  I, J, K: Integer;
  Aes128: Array Of Tkey128;
Begin
  Setlength(Aes128, Length(Keys));
  J := 0;
  While J < 3 Do
  Begin
    Keys[J] := '';
    I := 1;
    While I <= 16 Do
    Begin
      Case J Of
        1:
          Keys[J] := Keys[J] + Chr(0);
        {
          should be:
          00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
          62 63 63 63 62 63 63 63 62 63 63 63 62 63 63 63
          9B 98 98 C9 F9 FB FB AA 9B 98 98 C9 F9 FB FB AA
          90 97 34 50 69 6C CF FA F2 F4 57 33 0B 0F AC 99
          EE 06 DA 7B 87 6A 15 81 75 9E 42 B2 7E 91 EE 2B
          7F 2E 2B 88 F8 44 3E 09 8D DA 7C BB F3 4B 92 90
          EC 61 4B 85 14 25 75 8C 99 FF 09 37 6A B4 9B A7
          21 75 17 87 35 50 62 0B AC AF 6B 3C C6 1B F0 9B
          0E F9 03 33 3B A9 61 38 97 06 0A 04 51 1D FA 9F
          B1 D4 D8 E2 8A 7D B9 DA 1D 7B B3 DE 4C 66 49 41
          B4 EF 5B CB 3E 92 E2 11 23 E9 51 CF 6F 8F 18 8E
          }

        2:
          Keys[J] := Keys[J] + Chr(Strtoint('$FF'));
        {
          should be:
          FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
          E8 E9 E9 E9 17 16 16 16 E8 E9 E9 E9 17 16 16 16
          AD AE AE 19 BA B8 B8 0F 52 51 51 E6 45 47 47 F0
          09 0E 22 77 B3 B6 9A 78 E1 E7 CB 9E A4 A0 8C 6E
          E1 6A BD 3E 52 DC 27 46 B3 3B EC D8 17 9B 60 B6
          E5 BA F3 CE B7 66 D4 88 04 5D 38 50 13 C6 58 E6
          71 D0 7D B3 C6 B6 A9 3B C2 EB 91 6B D1 2D C9 8D
          E9 0D 20 8D 2F BB 89 B6 ED 50 18 DD 3C 7D D1 50
          96 33 73 66 B9 88 FA D0 54 D8 E2 0D 68 A5 33 5D
          8B F0 3F 23 32 78 C5 F3 66 A0 27 FE 0E 05 14 A3
          D6 0A 35 88 E4 72 F0 7B 82 D2 D7 85 8C D7 C3 26
          }

        3:
          Keys[J] := Keys[J] + Chr(I - 1);
        { should be:
          00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
          D6 AA 74 FD D2 AF 72 FA DA A6 78 F1 D6 AB 76 FE
          B6 92 CF 0B 64 3D BD F1 BE 9B C5 00 68 30 B3 FE
          B6 FF 74 4E D2 C2 C9 BF 6C 59 0C BF 04 69 BF 41
          47 F7 F7 BC 95 35 3E 03 F9 6C 32 BC FD 05 8D FD
          3C AA A3 E8 A9 9F 9D EB 50 F3 AF 57 AD F6 22 AA
          5E 39 0F 7D F7 A6 92 96 A7 55 3D C1 0A A3 1F 6B
          14 F9 70 1A E3 5F E2 8C 44 0A DF 4D 4E A9 C0 26
          47 43 87 35 A4 1C 65 B9 E0 16 BA F4 AE BF 7A D2
          54 99 32 D1 F0 85 57 68 10 93 ED 9C BE 2C 97 4E
          13 11 1D 7F E3 94 4A 17 F3 07 A7 8B 4D 2B 30 C5
          }

      End;
      Inc(I);
    End;

    Expandkey(Texttokey(Keys[J]), Aes128[J]);

    Keys[J] := '';
    K := 1;
    While K <= Length(Aes128[J]) Do
    Begin
      Keys[J] := Keys[J] + Inttohex(Aes128[J][K], 2) + Chr(32);
      If K Mod 16 = 0 Then
        Keys[J] := Keys[J] + #13#10;
      Inc(K);
    End;
    Inc(J);
  End;
End;

Procedure Taes.Keyschedule_core(Var Word: Tword; Iteration: Integer; Mode: Byte);
Begin
  Rotate(Word, Mode);
  Subbytes(Word);
  Word[1] := Word[1] Xor Byte(Rcon(Iteration));

End;

Function Taes.Galois_mult(A, B: Byte): Byte; //http://en.wikipedia.org/wiki/Rijndael_mix_columns
Var
  P, Counter, Hi_bit_set: Byte;
  Aa, Bb: Byte;

Begin
  Aa := A;
  Bb := B;
  P := 0;
  Counter := 0;
  While Counter < 8 Do
  Begin
    If (Bb And 1) <> 0 Then
      P := P Xor Aa;

    Hi_bit_set := Byte(Aa And $80); //Mod 256;
    Aa := Byte(Aa Shl 1);
    If Hi_bit_set <> 0 Then
      Aa := Byte(Aa Xor $1b); //x^8+x^4+x^3+x^2+x+1
    Bb := Bb Shr 1;
    Inc(Counter);
  End;
  Result := P;
End;

Function Taes.Multcolumn(Column: Tcolumn; Mode: Byte): Tcolumn;
//multiplies a column with the MDS matrix
{
  mds=
  2  3  1  1
  1  2  3  1
  1  1  2  3
  3  1  1  2

  mdsinv=
  14 11 13 9
  9  14 11 13
  13  9 14 11
  11 13  9 14

  where + = xor, x = galois-multiplication }


Begin
  Case Mode Of
    0:
      Begin

        Result[1] := (((Galois_mult(2, Column[1]) Xor Galois_mult(3, Column[2])) Xor Galois_mult
              (1, Column[3])) Xor Galois_mult(1, Column[4]));
        Result[2] := (((Galois_mult(1, Column[1]) Xor Galois_mult(2, Column[2])) Xor Galois_mult
              (3, Column[3])) Xor Galois_mult(1, Column[4]));
        Result[3] := (((Galois_mult(1, Column[1]) Xor Galois_mult(1, Column[2])) Xor Galois_mult
              (2, Column[3])) Xor Galois_mult(3, Column[4]));
        Result[4] := (((Galois_mult(3, Column[1]) Xor Galois_mult(1, Column[2])) Xor Galois_mult
              (1, Column[3])) Xor Galois_mult(2, Column[4]));
      End;
    1:
      Begin
        Result[1] := (((Galois_mult(14, Column[1]) Xor Galois_mult(11, Column[2])) Xor Galois_mult
              (13, Column[3])) Xor Galois_mult(9, Column[4]));
        Result[2] := (((Galois_mult(9, Column[1]) Xor Galois_mult(14, Column[2])) Xor Galois_mult
              (11, Column[3])) Xor Galois_mult(13, Column[4]));
        Result[3] := (((Galois_mult(13, Column[1]) Xor Galois_mult(9, Column[2])) Xor Galois_mult
              (14, Column[3])) Xor Galois_mult(11, Column[4]));
        Result[4] := (((Galois_mult(11, Column[1]) Xor Galois_mult(13, Column[2])) Xor Galois_mult
              (9, Column[3])) Xor Galois_mult(14, Column[4]));
      End;
  End;
End;

Procedure Taes.Mixcolumns(Var State: Tstate; Mode: Byte);

Var
  Column: Tcolumn;
  I, J: Integer;

Begin
  //identify columns
  J := 1;
  While J <= 4 Do
  Begin
    I := 1;
    While I <= 4 Do
    Begin
      Column[I] := State[I][J];
      Inc(I);
    End;
    Column := Multcolumn(Column, Mode);
    I := 1;
    While I <= 4 Do
    Begin
      State[I][J] := Column[I];
      Inc(I);
    End;
    Inc(J);
  End;
End;

Procedure Taes.Subbytes(Var State: Tstate; Mode: Byte); //ok
Var
  X: Byte;
  I, J: Integer;

Begin
  I := 1;
  While I <= 4 Do
  Begin
    J := 1;
    While J <= 4 Do
    Begin
      X := State[I][J];
      Case Mode Of
        0:
          X := Sbox[X];
        1:
          X := Invsbox[X];
      End;
      State[I][J] := X;
      Inc(J);
    End;
    Inc(I);
  End;
End;

Procedure Taes.Subbytes(Var Word: Tword);
Var
  I: Integer;
Begin
  I := 1;
  While I <= 4 Do
  Begin
    Word[I] := GetSBoxValue(Word[I]);
    Inc(I);
  End;
End;

Function Taes.Rcon(Index: Byte): Integer;
Var
  C, B: Integer;

Begin
  If Index = 0 Then
    Result := $8d
  Else
  Begin
    C := 1;
    While Index <> 1 Do
    Begin
      B := C And $80;
      C := C Shl 1;
      If B = $80 Then
        C := C Xor $1b;
      Dec(Index);
    End;
    Result := C;
  End;
End;

(* orig c code:
  -----------------
  {
  unsigned char c=1;
  if(in == 0)
  return 0;
  while(in != 1) {
  unsigned char b;
  b = c & 0x80;
  c <<= 1;
  if(b == 0x80) {
  c ^= 0x1b;
  }
  in--;
  }
  return c;
  }
  -----------------
  *)


Function Taes.Expandkey(Key: Tinput; Var Expandedkey: Tkey128): Byte; //correct!
//expands given key (128,192,256 bit, determined by bitlen variable) to (176,208,240 bytes)
//blocksize=16=>keysize 128 bit
//result:= the number of rounds (10,12,14) determined by new keylength
//SRC= http://www.samiam.org/key-schedule.html
//http://cboard.cprogramming.com/c-programming/87805-%5Btutorial%5D-implementing-advanced-encryption-standard.html
Var
  I, Rconiterator, A, C: Integer;
  Temp: Tword;
Begin
  I := 1;
  While I <= Length(Key) Do
  Begin
    Expandedkey[I] := Key[I];
    Inc(I);
  End;

  Rconiterator := 1;
  C := Length(Key) + 1; //17
  While C <= 176 Do
  Begin
    { Copy the temporary variable over from the last 4-byte- block }
    A := 1;
    While A <= 4 Do
    Begin
      Temp[A] := Expandedkey[A + C - 5];
      Inc(A);
    End;

    If ((C - 1) Mod 16 = 0) Then
    Begin
      Keyschedule_core(Temp, Rconiterator, 0);
      Inc(Rconiterator);
    End;
    A := 1;
    While A <= 4 Do
    Begin
      Expandedkey[C] := Expandedkey[C - 16] Xor Temp[A];
      Inc(C);
      Inc(A);
    End;
  End;

  Result := 11; //number of rounds for 128 bit keys
End;

Function Taes.Generatesubkeys(Expandedkey: Tkey128): Tsubkeys128;
Var
  I, J, K: Byte;
  X: Byte;
  Subkeystate: Tstate;
  Subkey: Tinput;
Begin
  I := 1;
  X := 1;
  While I < Length(Expandedkey) Do
  Begin
    J := I;
    K := 1;
    While K <= 16 Do
    Begin
      Subkey[K] := Expandedkey[J];
      Inc(K);
      Inc(J);
    End;

    Subkeystate := Keytostate(Subkey);
    Result[X] := Subkeystate;
    Inc(X);
    I := J;
  End;
End;

Function Taes.Expandkey(Key: Tinput; Var Expandedkey: Tkey192): Byte;
//expands given key (128,192,256 bit, determined by bitlen variable) to (176,208,240 bytes)
//blocksize=16=>keysize 128 bit
//result:=new keylength(determines the number of rounds (10,12,14)
//SRC= http://www.samiam.org/key-schedule.html
//http://cboard.cprogramming.com/c-programming/87805-%5Btutorial%5D-implementing-advanced-encryption-standard.html
Var
  I: Integer;
  Currentsize, Size: Integer;
  Rconiteration: Integer;
  Temp: Tword;
Begin
  Rconiteration := 1;
  Size := Length(Key);
  I := 1;
  While I <= 4 Do
  Begin
    Temp[I] := 0;
    Inc(I);
  End;
  Currentsize := 0;
  I := 1;
  While I <= Size Do
  Begin
    Expandedkey[I] := Key[I];
    Inc(I);
  End;
  Currentsize := Currentsize + Size;
  // assign the previous 4 bytes to the temporary value t
  While Currentsize < Length(Expandedkey) Do
  Begin
    I := 1;
    While I <= 4 Do
    Begin
      Temp[I] := Expandedkey[(Currentsize - 4) + I];
      Inc(I);
    End;
    //every 16,24,32 bytes (respective length of tinput) we apply the core schedule to t and increment rconIteration afterwards

    If Currentsize Mod Size = 0 Then
    Begin
      Keyschedule_core(Temp, Rconiteration + 1, 0);
      Inc(Rconiteration);
    End;

    {
      We XOR t with the four-byte block 16,24,32 bytes before the new expanded key.
      * This becomes the next four bytes in the expanded key.
      }


    I := 1;
    While I <= 4 Do
    Begin
      Expandedkey[Currentsize] := Expandedkey[Currentsize - Size] Xor Temp[I];
      Inc(Currentsize);
      Inc(I);
    End;

  End;
  Result := 12; //number of rounds for 192 bit keys
End;

Function Taes.Expandkey(Key: Tinput; Var Expandedkey: Tkey256): Byte;
//expands given key (128,192,256 bit, determined by bitlen variable) to (176,208,240 bytes)
//blocksize=16=>keysize 128 bit
//result:=new keylength(determines the number of rounds (10,12,14)
//SRC= http://www.samiam.org/key-schedule.html
//http://cboard.cprogramming.com/c-programming/87805-%5Btutorial%5D-implementing-advanced-encryption-standard.html
Var
  I: Integer;
  Currentsize, Size: Integer;
  Rconiteration: Integer;
  Temp: Tword;
Begin
  Rconiteration := 1;
  Size := Length(Key);
  I := 1;
  While I <= 4 Do
  Begin
    Temp[I] := 0;
    Inc(I);
  End;
  Currentsize := 0;
  I := 1;
  While I <= Size Do
  Begin
    Expandedkey[I] := Key[I];
    Inc(I);
  End;
  Currentsize := Currentsize + Size;
  // assign the previous 4 bytes to the temporary value t
  While Currentsize < Length(Expandedkey) Do
  Begin
    I := 1;
    While I <= 4 Do
    Begin
      Temp[I] := Expandedkey[(Currentsize - 4) + I];
      Inc(I);
    End;
    //every 16,24,32 bytes (respective length of tinput) we apply the core schedule to t and increment rconIteration afterwards

    If Currentsize Mod Size = 0 Then
    Begin
      Keyschedule_core(Temp, Rconiteration + 1, 0);
      Inc(Rconiteration);
    End;

    //applies only to 256 bit keys: For 256-bit keys, we add an extra sbox to the calculation
    If (Size = 32) And (Currentsize Mod Size = 16) Then
    Begin
      I := 1;
      While I <= 4 Do
      Begin
        Temp[I] := Getsboxvalue(Temp[I]);
        Inc(I);
      End;

    End;

    {
      We XOR t with the four-byte block 16,24,32 bytes before the new expanded key.
      * This becomes the next four bytes in the expanded key.
      }


    I := 1;
    While I <= 4 Do
    Begin
      Expandedkey[Currentsize] := Expandedkey[Currentsize - Size] Xor Temp[I];
      Inc(Currentsize);
      Inc(I);
    End;

  End;
  Result := 14; //number of rounds for 256 bit keys
End;

Function Taes.Texttostate(Substr: String): Tstate;
//max length 16!!
Var
  I, J: Integer;
  Row: Trow;

Begin
  If Length(Substr) > 16 Then
  Begin
    Raise Exception.Create('No valid substring length');
    Exit;
  End;

  I := 1;
  While I <= 4 Do
  Begin
    J := 1;
    While J <= 4 Do
    Begin
      Row[J] := Ord(Substr[J + 4 * (I - 1)]);
      Inc(J);

    End;
    Result[I] := Row;
    Inc(I);
  End;

End;

Function Taes.Keytostate(Data: Tinput): Tstate;
Var
  I, J: Integer;
  Row: Trow;

Begin

  I := 1;
  While I <= 4 Do
  Begin
    J := 1;
    While J <= 4 Do
    Begin
      Row[J] := Ord(Data[J + 4 * (I - 1)]);
      Inc(J);

    End;
    Result[I] := Row;
    Inc(I);
  End;
End;

Function Taes.Statetotext(State: Tstate): String;
Var
  I, J: Int64;

Begin
  Result := '';
  I := 1;
  While I <= 4 Do
  Begin
    J := 1;
    While J <= 4 Do
    Begin
      Result := Result + Chr(State[I][J]);
      Inc(J);
    End;
    Inc(I);
  End;
End;

Function Taes.Texttokey(Key: String): Tinput;
Var
  I: Byte;
Begin
  If Length(Key) > 16 Then
    Raise Exception.Create('Keylength not accepted. Must be <=16')
  Else
  Begin

    I := 1;
    While I <= Length(Key) Do
    Begin
      Result[I] := Ord(Key[I]);
      Inc(I);
    End;
    While I < 16 Do
    Begin
      Result[I] := 0;
      Inc(I);
    End;

  End;

End;

Procedure Taes.Showstate(State: Tstate; Memo: Tmemo);
Var
  I, J: Integer;
  Row: Trow;
  R: String;

Begin
  I := 1;
  While I <= 4 Do
  Begin
    J := 1;
    R := '';
    While J <= 4 Do
    Begin
      Row[J] := State[I][J];
      R := R + Inttostr(Row[J]) + Chr(32);
      Inc(J);
    End;
    Memo.Lines.Add(R);
    Inc(I);
  End;
End;

Procedure Taes.Shiftrows(Var State: Tstate; Mode: Byte); //ok
  Function Rowshift(Row: Trow; Count, Mode: Byte): Trow;
  Var
    I, K: Integer;

  Begin
    I := 1;
    While I <= 4 Do
    Begin
      If Mode = 0 Then
      Begin
        K := (I + Count);
        If K > 4 Then
          K := K - 4;
      End
      Else If Mode = 1 Then
      Begin
        K := (I - Count);
        If K < 1 Then
          K := K + 4;
      End;
      Result[I] := Row[K];
      Inc(I);
    End;
  End;

Var
  I: Integer;
Begin
  If (Mode = 0) Or (Mode = 1) Then
  Begin
    I := 1;
    While I <= 4 Do
    Begin
      State[I] := Rowshift(State[I], I - 1, Mode);
      Inc(I);
    End;
  End
  Else
    Exit;
End;

// rotate(1d 2c 3a 4f) = 2c 3a 4f 1d
//tword is 4byte long, Rotation 8 bit (=1byte) to the left=shifting one entry to the left
Procedure Taes.Rotate(Var Value: Tword; Mode: Byte);
Var
  I, J: Byte;
  Result: Tword;

Begin
  Case Mode Of

    0:
      Begin
        I := 1;
        While I <= 4 Do
        Begin
          J := I + 1;
          If J > 4 Then
            J := J - 4;

          Result[I] := Value[J];
          Inc(I);
        End;
      End;

    1:
      Begin
        I := 1;
        While I <= 4 Do
        Begin
          J := I - 1;
          If J <= 0 Then
            J := J + 4;

          Result[I] := Value[J];
          Inc(I);
        End;
      End;
  End;
  Value := Result;
End;

Procedure Taes.AddRoundKey(Var State: Tstate; Roundkey: Tstate);
Var
  I, J: Integer;

Begin
  I := 1;
  While I <= 4 Do
  Begin
    J := 1;
    While J <= 4 Do //one row
    Begin
      State[I][J] := State[I][J] Xor Roundkey[I][J];
      Inc(J);
    End;
    Inc(I);
  End;
End;

Function Taes.Getsboxvalue(Index: Byte): Byte;
Begin
  Result := Sbox[Index];
End;

Function Taes.Getinvsboxvalue(Index: Byte): Byte;
Begin
  Result := Invsbox[Index];
End;

Procedure Taes.Aes(Roundcount: Byte; Var State: Tstate; Keys: Tsubkeys128; Mode: Byte);
Var
  I: Integer;

Begin
  If Mode = 0 Then
  Begin
    I := 1;
    Addroundkey(State, Keys[I]);
    Inc(I);
    While I <= Roundcount - 1 Do
    Begin
      Subbytes(State, Mode);
      Shiftrows(State, Mode);
      Mixcolumns(State, Mode);
      Addroundkey(State, Keys[I]);
      Inc(I);
    End;
    // final round :
    Subbytes(State, Mode);
    Shiftrows(State, Mode);
    Addroundkey(State, Keys[I]);
  End

  Else
  Begin
    I := Roundcount;
    //decryption= go backwards from last step on
    Addroundkey(State, Keys[I]);
    Shiftrows(State, Mode);
    Subbytes(State, Mode);
    I := I - 1;
    While I >= 2 Do
    Begin
      Addroundkey(State, Keys[I]);
      Mixcolumns(State, Mode);
      Shiftrows(State, Mode);
      Subbytes(State, Mode);
      Dec(I);

    End;
    Addroundkey(State, Keys[I]);
  End;
End;

Function Taes.Aes_text(Var Text, Key: String; Bitlen: Integer; Mode: Byte): String;
Var
  Substr: String;
  I, J, Textlen: Int64;
  State: Tstate;
  Keystate: Tinput;
  Roundcount: Integer;
  Subkeys: Tsubkeys128;

Begin
  Textlen := Length(Text);
  //padding
  While Textlen Mod 16 <> 0 Do
  Begin
    Text := Text + Chr(0);
    Inc(Textlen);
  End;

  Keystate := Texttokey(Key);
  Case Bitlen Of
    128:
      Roundcount := Expandkey(Keystate, Expandedkey128);
    192:
      Roundcount := Expandkey(Keystate, Expandedkey192);
    256:
      Roundcount := Expandkey(Keystate, Expandedkey256);
  Else
    Begin
      Result := Text;
      Raise Exception.Create('Keysize not accepted.');
    End;

  End;

  Subkeys := Generatesubkeys(Expandedkey128);

  If Roundcount <> -1 Then
  Begin
    I := 1;
    While I <= Textlen Do
    Begin
      J := I;
      Substr := '';
      While J < I + 16 Do
      Begin
        Substr := Substr + Text[J];
        Inc(J);
      End;
      State := Texttostate(Substr);
      Aes(Roundcount, State, Subkeys, Mode);
      Substr := Statetotext(State);
      Result := Result + Substr;
      I := J;
    End;
  End

  Else
    Result := Text; //an error occurred
End;

End.

besten dank
  Mit Zitat antworten Zitat