Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Rijndael (AES) Verschlüsselung in DLL: Zugriffsverletzung


stiftmaster - So 03.07.05 15:37
Titel: Rijndael (AES) Verschlüsselung in DLL: Zugriffsverletzung
Hallo Leute,

stecke zur Zeit an der AES-Verschlüsselung. Diese möchte ich in eine DLL packen. Das klappt auch soweit schon recht gut. Folgend der Code meiner DLL:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
library Project1;

uses
  Cipher1 in 'Cipher1.pas', Classes, IdBaseComponent, IdCoder, IdCoder3to4,
  IdCoderMIME;

const
  Codes64 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/';

function fEnc_Base64(const Value: string): string;
var
  I, A, X, B: Integer;
begin
  Result := '';
  A := 0;
  B := 0;
  for I := 1 to Length(Value) do
  begin
    X := Ord(Value[I]);
    B := B * 256 + X;
    A := A + 8;
    while A >= 6 do
    begin
      A := A - 6;
      X := B div (1 shl A);
      B := B mod (1 shl A);
      Result := Result + Codes64[X + 1];
    end;
  end;
  if A > 0 then
  begin
    X := B shl (6 - A);
    Result := Result + Codes64[X + 1];
  end;
end;

function fEnc_AES(const Value, Key: string): string;
var
  AES: TCipher_Rijndael;
begin
  AES := TCipher_Rijndael.Create(Key, nil);
  Result := AES.EncodeString(Value);
  AES := nil;
  AES.Free;
end;

function EncodeString(const Value, Key: PChar): PChar; stdcall;
var
  TempResult, TempKey, DummyString: string;
begin
  try
    SetLength(TempResult, Length(Value) + 1);
    TempResult := Value;

    SetLength(TempKey, Length(Key) + 1);
    TempKey := Key;

    TempResult := fEnc_Base64(TempResult);
>>> TempResult := fEnc_AES(TempResult, TempKey);
    
    Result := PChar(TempResult);
  except
    Result := Value;
  end;
end;

exports
  EncodeString,

begin

end.


Zum Testen habe ich mir ein kleines Programm gebastelt, um die Verschlüsselung zu testen. Dieses hat eine Memo-Eingabe und ein Label für die Ausgabe. Code wie folgt:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Cipher1, IdBaseComponent, IdCoder, IdCoder3to4, IdCoderMIME;

type
  TForm1 = class(TForm)
    EncodeButton: TButton;
    Memo1: TMemo;
    Label1: TLabel;
    procedure EncodeButtonClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

const
  cDLL_Name = 'Project1.dll';

function EncodeString(const Value, Key: PChar): PChar; stdcallexternal cDLL_Name;

implementation

{$R *.dfm}

procedure TForm1.EncodeButtonClick(Sender: TObject);
var
  TempString: string;
  AES: TCipher_Rijndael;
begin
  Label1.Caption := EncodeString(PChar(Memo1.Text), PChar('pwd'));;
end;

end.


In das Memo-Feld habe ich jetzt einfach n' bissle Delphi-Code kopiert, damit dieser verschlüsselt werden kann. Dieser sieht wie folgt aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
Memo2
function DecodeString(Value, Key: PChar): PChar; stdcall;
var
  AES: TCipher_Rijndael;
  Dec_Base64: TIdDecoderMIME;
  TempResult: string;
begin
  try
    Result := Value;

    Dec_Base64 := TIdDecoderMIME.Create(nil);
    AES := TCipher_Rijndael.Create(Key, nil);

    TempResult := Dec_Base64.DecodeString(Value);
    TempResult := AES.DecodeString(TempResult);
    Result := PChar(TempResult);
  finally
    AES := nil;
    AES.Free;
    Dec_Base64 := nil;
    Dec_Base64.Free;
  end;
end;function DecodeString(Value, Key: PChar): PChar; stdcall;
var
  AES: TCipher_Rijndael;
  Dec_Base64: TIdDecoderMIME;
  TempResult: string;
begin
  try
    Result := Value;

    Dec_Base64 := TIdDecoderMIME.Create(nil);
    AES := TCipher_Rijndael.Create(Key, nil);

    TempResult := Dec_Base64.DecodeString(Value);
    TempResult := AES.DecodeString(TempResult);
    Result := PChar(TempResult);
  finally
    AES := nil;
    AES.Free;
    Dec_Base64 := nil;
    Dec_Base64.Free;
  end;
end;


Wenn ich jetzt auf den Button klicke, funktioniert das Verschlüsseln einwandfrei, klicke ich öfters drauf, läuft es auch einwandfrei - aber irgendwann, nach dem X-ten klicken (mal ist es das zweite, mal das 10, mal das 30) kommt auf einmal eine Zugriffsverletzung aus der DLL.

Daraufhin habe ich den Code aus der DLL in die Unit kopiert, dort ebenfalls x-mal auf verschlüsseln geklickt und es kam einfach keine Zugriffsverletzugn.

Dann bin ich hingegangen und habe in der DLL nach und nach einige Zeilen auskommentiert um herauszubekommen, welche Zeile den Ärger macht. Irgendwann hatte ich die Zeile raus - es ist die mit der AES-Verschlüsselung, im Code mit >>> markiert. Lasse ich die draußen, gibt es keine Zugriffsverletzung aber auch keine Verschlüsselung ;-)

Kann sich das jemand von euch erklären. Was mache ich falsch - verstehe es einfach nicht...

Stefan

Moderiert von user profile iconraziel: Code- durch Delphi-Tags ersetzt.


MSCH - So 03.07.05 19:47

ich vermute, da du Strings verwendest und dlls per se damit nicht viel anfangen können.
Nimm die Unit ShareMem als erstes in deine DLL auf.

grez
msch