Entwickler-Ecke

Sonstiges (Delphi) - Verschlüsseln ohne #0, #10 und #13


AXMD - So 18.01.04 13:03
Titel: Verschlüsseln ohne #0, #10 und #13
Hi,

ich möchte die Datendatei einer meiner Programme verschlüsseln. Hab mich schon ein bisschen im Algorithmen-Programmieren versucht, aber mir passiert immer wieder Folgendes: es tauchen immer wieder Zeichenkombinationen auf, die anschließend als #0, #10 oder #13 verschlüsselt werden - mit dem Resultat, dass die Dateien nicht wieder geöffnet werden können. Was kann ich tun, um dieses Problem zu vermeiden.

AXMD

PS.: Ich habe schon xor und alles Mögliche durchprobiert, aber nichts scheint wirklich zu funktionieren. "Fremde" (nicht selbst programmierte) Verschlüsselungen möchte ich möglichst vermeiden


tomtom62 - So 18.01.04 13:28

Warum können diese Dateien nicht geöffnet werden ?.

Wie öffnest Du diese ?

Ein paar mehr Details wären nett :wink:

Allgemein gilt: Am besten (sichersten) für einen Algorithmus ist es, wenn alle Zeichen gleich häufig vorkommen. Ansonsten hat man einen ersten Ansatz zum Knacken.


derDoc - So 18.01.04 13:41

Ich weiß zwar nicht welchen Algorithmus du verwendest, aber du kannst doch sicherlich prüfen, ob eines jener Zeichen herauskommt und dann nochmals das Vorherige verschlüsseln.

Wenn deine Dateien sicher sein sollen, dann sollten zwei identische Zeichen nicht die selben Zeichen ergeben.

Beispiel:

a -> #0
einfach nochmal a verschlüsseln
a -> #89
(sofern dein Algorithmus das kann)


AXMD - So 18.01.04 13:47

@derdoc: das kann mein Algorithmus.

Das Problem ist nur, dass #10 bzw. #13 eine Zeilenumbruch erzeugen. Da die Datei zeilenweise ausgelesen wird, bricht das Programm ab, da die Daten ja erst in der nächsten Zeile stehen. Und wenn #0 beim Verschlüsseln rauskommt, fehlt das Zeichen ganz.

AXMD

//EDIT: hier der Code (die Konstanten-Arrays sind nicht komplett abgebildet (durch ... gekennzeichnet) - sonst würde ja meine Verschlüsselung nichts nützen)


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:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
unit ds_code;

interface

const
  CodeTableSize = 10;

  acodetable: Array [0..CodeTableSize, 0..CodeTableSize] of Byte = (...);

  ADefaultString = ...;

type
  _TABLE = Array [0..CodeTableSize, 0..CodeTableSize] of Byte;

const
  axortable: _TABLE = (...);

  aorder: Array [0..CodeTableSize] of Byte = (...);
  border: Array [0..CodeTableSize] of Byte = (...);
  corder: Array [0..CodeTableSize] of Byte = (...);
  dorder: Array [0..CodeTableSize] of Byte = (...);
  eorder: Array [0..CodeTableSize] of Byte = (...);
  forder: Array [0..CodeTableSize] of Byte = (...);

function Letter_xor(ALetter, A2ndLetter: Char): Char;
function Letter_Num_xor(ALetter: Char; ANum: Byte): Char;
function String_xor(AString, A2ndString: String): String;
function Table_xor(AString: String; Index: Byte): String;
function XTable_xor(AString: String): String;
function XXorEx_(AString: String; Table: _TABLE): String;
function XXorEx(AString: String): String;
function Move1(AString: String; Order: Array of Byte): String;
function DoMove(AString: String): String;

function EncodeDS(AString: String): String;
function DecodeDS(AString: String): String;

implementation

function Letter_xor(ALetter, A2ndLetter: Char): Char;
begin
  Result := Chr(Ord(ALetter) xor Ord(A2ndLetter));
end;

function Letter_Num_xor(ALetter: Char; ANum: Byte): Char;
begin
  Result := Chr(Ord(ALetter) xor ANum);
end;

function String_xor(AString, A2ndString: String): String;
var
  i: Integer;
begin
  Result := '';
  for i := 1 to Length(AString) do
    Result := Result + Letter_xor(AString[i], A2ndString[i mod Length(A2ndString) - 1]);
end;

function Table_xor(AString: String; Index: Byte): String;
var
  i: Integer;
begin
  Result := '';
  for i := 1 to Length(AString) do
    Result := Result + Letter_Num_xor(AString[i], acodetable[i mod CodeTableSize, Index]);
end;

function XTable_xor(AString: String): String;
var
  i: Byte;
begin
  Result := AString;
  for i := 0 to CodeTableSize do
    Result := Table_xor(Result, i);
end;

function XXorEx_(AString: String; Table: _TABLE): String;
var
  i, j: Byte;
  dummy, dummy2: String;
begin
  dummy := AString;
  for i := 0 to CodeTableSize do begin
    dummy2 := '';
    for j := 1 to Length(AString) do
      dummy2 := dummy2 + Letter_Num_xor(dummy[j], Table[j mod CodeTableSize, aorder[i]]);
    dummy := dummy2;
    end;
  Result := dummy;
end;

function XXorEx(AString: String): String;
begin
  Result := XXorEx_(AString, axortable);
  Result := XXorEx_(Result, a2x_table);
end;

function Move1(AString: String; Order: Array of Byte): String;
var
  i: Integer;
begin
  Result := AString;
  for i := 1 to Length(Result) do begin
    if i mod 2 = 0 then
      Result[i] := Chr(Ord(Result[i]) xor not Order[i mod CodeTableSize])
    else
      Result[i] := Chr(Ord(Result[i]) xor Order[i mod CodeTableSize]);
    end;
end;

function DoMove(AString: String): String;
begin
  Result := Move1(AString, aorder);
  Result := Move1(Result, border);
  Result := Move1(Result, corder);
  Result := Move1(Result, dorder);
  Result := Move1(Result, eorder);
  Result := Move1(Result, forder);
end;

function EncodeDS(AString: String): String;
begin
  Result := String_xor(AString, ADefaultString);
  Result := XXorEx(Result);
end;

function DecodeDS(AString: String): String;
begin
  Result := XXorEx(AString);
  Result := String_xor(Result, ADefaultString);
end;

end.


tomtom62 - So 18.01.04 14:31

Du musst nicht zeilerweise einlesen. Wenn Du z.B. einen TFileStream benutzt und das alles in einen String einliest, dann sind diese Zeichen kein Problem...


MSCH - So 18.01.04 14:35

warum so kompliziert ? Schau mal hier: http://sourceforge.net/projects/tplockbox

da findest du diverse Verschlüsselungsalgos:
.
Völlig frei und nicht so einfach zu knacken.
grez
msch


derDoc - Mo 19.01.04 18:42

Ich würde dir empfehlen, in deine Verschlüsselungen zu prüfen, ob ein Zeichen zu #0, #10 oder #13 wird und dann per rekursion nochmals zu verschlüsseln.

Dazu würde ich dir eine Prozedur empfehlen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure Letter_xor(ALetter, A2ndLetter: Char; var Letter: Char); 
begin
  Letter := Chr(Ord(ALetter) xor Ord(A2ndLetter));
  if Letter = #0 then
    Letter_xor(ALetter, A2ndLetter, Letter); 
end;

(...)

procedure Was_Weiß_Ich;
var
  Buchstabe: Char;
begin
  Letter_xor('f''h', Buchstabe);
  Label1.Caption := Label1.Caption + Buchstabe;
end;


Anonymous - Mo 19.01.04 18:51

Das lässt sich aber auch iterativ lösen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure Letter_xor(ALetter, A2ndLetter: Char; var Letter: Char); 
begin
 repeat
  Letter := chr(ord(ALetter) xor ord(A2ndLetter));
 until Letter <> #0;
end;


Motzi - Mo 19.01.04 18:52

Warum so kompliziert den Algo ändern (abgesehen davon, dass ich keinen eigenen Algo sondern einen bekannten sicheren nehmen würde), und nicht einfach eine flexiblere Art des Auslesens verwenden - sprich TFileStream (wie bereits erwähnt wurde)...!


derDoc - Mo 19.01.04 19:15

Also ich würde schon einen eigenen Algorithmus nehmen, wenn du etwas sichern willst. Dadurch wird es schließlich noch schwerer die Datei zu entschlüsseln, da du ja nichtmal den Algorithmus kennst, bzw. kein populärer Algorithmus verwendet wird.
(Natürlich nur, wenn der eigene Algorithmus auch entsprechend sicher ist, was einiger Zeit der Entwicklung bedarf).

Aber ich muss Motzi zustimmen, dass ein FileStream komfortabler ist.


Anonymous - Mo 19.01.04 19:24

Diese Algorithmen sind sicher genug, dass niemand auf die Idee kommen wird, mehr Rechenleistung als auf diesem Planeten zur Verfügung steht darin zu investieren, die Datendatei von einem Programm, dass 2 Hand voll Leute benutzen, zu knacken.

Abgesehen davon: Man kann die Exe disassemblisieren / debuggen und schon hat man den Algorithmus


MSCH - Mo 19.01.04 19:26

Auch ein populärer offener Schlüssel ist nicht zu knacken.
Der Vorteil, alles getestet und geprüft. Entsprechende Komponenten gibts als Freeware mittlerweile. Warum dann noch tüffteln, wie ein eigener Code nicht zu knacken ist ?

grez
msch


AXMD - Sa 24.01.04 13:22

obbschtkuche hat folgendes geschrieben:
Das lässt sich aber auch iterativ lösen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure Letter_xor(ALetter, A2ndLetter: Char; var Letter: Char); 
begin
 repeat
  Letter := chr(ord(ALetter) xor ord(A2ndLetter));
 until Letter <> #0;
end;


Danke für den Tipp, aber ihr habt einen kleinen Denkfehler drinnen: man erhält eine Endlosschleife, da Letter immer aus den gleichen Daten berechnet wird - und so #0 bleibt wenn es schon #0 war.
Richtig wäre:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure Letter_xor(ALetter, A2ndLetter: Char; var Letter: Char); 
begin
  Letter := ALetter;
  repeat
    Letter := Chr(Ord(Letter) xor Ord(A2ndLetter));
  until
    Letter <> #0;
end;


Aber auch wenn ichs so probiere, versagt mein Algo - k.A. warum :?:. Außerdem muss ich irgendwo noch einen Bug begraben haben - der Algo kann nämlich keine Strings über 255 Zeichen kodieren (nur Länge mod 255 !?). Wenn ich die Probleme behoben habe, werd ich den neuen Quelltext posten und dann können wir ja nochmal versuchen, ob die repeat-Schleife hinhaut ;)

MfG AXMD


Anonymous - Sa 24.01.04 13:36

Tut mir Leid, ich hatte mir den Code garnicht näher angeschaut.
Ich würde dir wirklich empfehlen einen der oben genannten Algorithmen zu nutzen. Letztendlich ist es aber sowieso egal, weil du das Pwd ja irgendwo speichern musst, und dann kommt man sowieso (fast) ohne Probleme an die Daten.