// Es wird mit einfachen Mitteln eine Unkenntlichmachung von Strings erreicht. // Siehe dazu auch Dateien verschlüsseln. // Für Textdateien siehe Punkte 8, 9 und 10 // 1. String mit Hilfe von Random unter Vermeidung von #0 verschlüsseln // Getestet mit RS 10.4 unter W11 // Durch Veränderung der Variablen "Value" zwischen 0 und 28.672 kann selbst bei // gleichem Passwort ein anderes Ergebnis erzielt werden.
type
Rnd = 0 .. $7000;
var
Value: Rnd = 14336; // z.B.
procedure coincidence(PW: string);
var
x, z, v, i: integer;
begin
i := 0;
v := 7;
for z := 2 to 11 do
begin
for x := 1 to length(PW) do
v := (v * 2 + ord(PW[x]) * z) mod 73;
i := i + v mod 10;
end;
randseed := 17 + i;
end;
function Crypt(const S, Key: WideString; EnCrypt: Boolean): WideString;
var
i: integer;
w, v: Word;
procedure makew;
begin
v := (v + random(99)) and MaxWord;
w := w xor random(v);
end;
procedure en;
begin
makew;
if w = 0 then
w := $FFFC;
end;
procedure de;
begin
if w = $FFFC then
w := 0;
makew;
end;
begin
Setlength(Result, length(S));
v := Value + $6789;
coincidence(Key);
for i := 1 to length(S) do
begin
w := ord(S[i]);
if EnCrypt then
en
else
de;
Result[i] := WideChar(w);
end;
end;
// Beispiel Verschlüsselung Memo1 --> Memo2
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo2.text := Crypt(Memo1.text, 'password', True);
end;
// Beispiel Entschlüsseln Memo2 selbst
procedure TForm1.Button2Click(Sender: TObject);
begin
Memo2.text := Crypt(Memo2.text, 'password', False);
end;
//---------------------------------------------------------------------
// 2. Text mittels Substitution verschlüsseln
// Getestet mit D2010 unter W10
// Eine einfache Art der Verschlüsselung, welche der XOR-Verschlüsselung
// ähnelt, aber nicht als solche erkennbar ist.
type
art = (Verschluesseln, Entschluesseln);
var
TestString: string = '';
function CryptTxt(txt, schlssl: string; like: art): string;
const
z = 31;
var
x, g: Integer;
pt, ps, pr: PChar;
begin
result := txt;
if txt = '' then
exit;
pt := @txt[1];
ps := @schlssl[1];
pr := @result[1];
for x := 1 to length(txt) do
begin
if like = Verschluesseln then
g := ord(pt^) + ord(ps^) - z
else
g := ord(pt^) - ord(ps^) + z;
pr^ := chr(g);
inc(pt);
inc(pr);
inc(ps);
if ps^ = #0 then
ps := @schlssl[1];
end;
end;
// Beispielaufruf
procedure TForm1.Button1Click(Sender: TObject);
begin
RichEdit1.PlainText := True;
TestString := CryptTxt(RichEdit1.Text, 'DBR-Delphi', Verschluesseln);
RichEdit1.Text := TestString;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
RichEdit1.Text := CryptTxt(TestString, 'DBR-Delphi', Entschluesseln);
end;
//---------------------------------------------------------------------
3. Erweiterung von 2.
// Getestet mit RS 10.4 unter W11
// Hierbei werden dem Ergebnis Prüfziffern vom Text und vom Passwort
// übergeben, wobei vorher das Passwort zusätzlich verschleiert wird.
// Durch Einbeziehung des Zufalls kann der verschlüsselte Text jedesmal
// anders aussehen. Außerdem wird durch den Wechsel zwischen RawByteString
// und String das Ergebnis völlig unleserlich.
type
C2 = array [0 .. 1] of Char;
sls = array [0 .. 19] of Byte;
Buch = array [0 .. 223] of Byte;
var
SB: Buch;
schls: sls;
procedure makeSB(rb: RawByteString; lg: Integer);
var
I: Integer;
function makeKey(rb: RawByteString; lg: Integer): sls;
var
I, X: Integer;
begin
X := 1;
for I := 0 to 19 do
begin
Result[I] := (SB[I] xor ord(rb[X])) and $F7;
inc(X);
if X > lg then
X := 1;
end;
end;
procedure Swap(n, M: Byte);
var
tmp: Byte;
begin
tmp := SB[n];
SB[n] := SB[M];
SB[M] := tmp;
end;
begin
for I := Low(SB) to High(SB) do
SB[I] := I + 32;
for I := High(SB) downto 0 do
Swap(I, random(I));
schls := makeKey(rb, lg);
end;
function hash(const s: string): C2;
var
X, z, erg, lg: Integer;
a: ansistring;
P: PChar;
begin
a := '';
erg := 1;
lg := length(s);
for z := 2 to 5 do
begin
for X := 1 to lg do
erg := (erg * 2 + ord(s[X]) * (z - ord(odd(X)) * (z - 1))) mod 93;
a := a + AnsiChar(erg mod 10);
end;
P := @a[1];
Result[0] := P^;
inc(P);
Result[1] := P^;
end;
function CryptTxt(txt: RawByteString; lg: Integer; like: Boolean)
: RawByteString;
const
z = 31;
var
X, Y: Integer;
g: AnsiChar;
pt, pr: PAnsiChar;
begin
Result := txt;
pt := @txt[1];
pr := @Result[1];
Y := 0;
for X := 1 to lg do
begin
if like then
g := AnsiChar(ord(pt^) + schls[Y] - z)
else
g := AnsiChar(ord(pt^) - schls[Y] + z);
pr^ := g;
inc(pt);
inc(pr);
inc(Y);
if Y > 19 then
Y := 0;
end;
end;
function encode(const txt, Passw: String; out erg: String): Byte;
var
Start: Byte;
rb: RawByteString;
lt, I: Integer;
Pc: PChar;
C: C2;
HT: string;
begin
erg := '';
try
if txt = '' then
begin
Result := 1;
exit;
end;
lt := length(Passw);
if not(lt in [3 .. 10]) then
begin
Result := 2;
exit;
end;
C := hash(Passw);
HT := hash(txt);
Start := GettickCount and $FF;
RandSeed := Start;
lt := lt * 2;
SetLength(rb, lt);
CopyMemory(@rb[1], @Passw[1], lt);
makeSB(rb, lt);
lt := length(txt) * 2;
SetLength(rb, lt);
CopyMemory(@rb[1], @txt[1], lt);
rb := CryptTxt(rb, lt, True);
Pc := @rb[1];
I := 1;
while I < lt do
begin
erg := erg + Pc^;
inc(I, 2);
inc(Pc);
end;
erg := C[0] + Char(Start or $500) + erg + C[1];
erg := HT + hash(erg) + erg;
Result := 0;
except
Result := 255;
end;
end;
function decode(const txt, Passw: String; out erg: String): Byte;
var
s, HT: string;
Start: Byte;
rb: RawByteString;
lt, I: Integer;
Pc: PChar;
C: C2;
begin
erg := '';
try
lt := length(txt);
if lt < 4 then
begin
Result := 1;
exit;
end;
HT := copy(txt, 1, 2);
s := copy(txt, 3, maxint);
C[0] := s[1];
C[1] := s[2];
s := copy(s, 3, maxint);
if hash(s) <> C then
begin
Result := 2;
exit;
end;
lt := length(s);
C[0] := s[1];
C[1] := s[lt];
if C <> hash(Passw) then
begin
Result := 3;
exit;
end;
s := copy(s, 2, lt - 2);
Start := ord(s[1]) and $FF;
s := copy(s, 2, maxint);
RandSeed := Start;
lt := length(Passw) * 2;
SetLength(rb, lt);
CopyMemory(@rb[1], @Passw[1], lt);
makeSB(rb, lt);
lt := length(s) * 2;
SetLength(rb, lt);
CopyMemory(@rb[1], @s[1], lt);
rb := CryptTxt(rb, lt, False);
s := '';
Pc := @rb[1];
I := 1;
while I < lt do
begin
s := s + Pc^;
inc(I, 2);
inc(Pc);
end;
if HT <> hash(s) then
begin
Result := 4;
exit;
end;
erg := s;
Result := 0;
except
Result := 255;
end;
end;
// Beispielaufrufe:
// Memo1 verschlüsseln...
procedure TForm1.Button1Click(Sender: TObject);
var
Passwort, s, r: string;
b: Byte;
begin
// -------- Nur zum Testen -----------------------------------
Memo1.Clear;
Memo1.Lines.Add('Das ist ein Versuch: @¾¿?????? ÄÖÜßäöü ???');
Passwort := '¿??*12Ä';
// -----------------------------------------------------------
// Passwort := Edit1.Text;
b := encode(Memo1.Text, Passwort, s);
case b of
0:
begin
r := 'OK';
Memo1.Text := s;
end;
1:
r := 'Kein Text zum Verschlüsseln gefunden';
2:
r := 'Passwort muss 3 bis 10 Zeichen haben';
else
r := 'Unbekannter Fehler';
end;
ShowMessage(r);
end;
// ...und wieder entschlüsseln
procedure TForm1.Button2Click(Sender: TObject);
var
b: Byte;
r, s: string;
begin
b := decode(Memo1.Text, '¿??*12Ä', s);
case b of
0:
begin
Memo1.Text := s;
r := 'OK';
end;
1:
r := 'Kein ordnungsgemäßer Text zum Entschlüsseln gefunden';
2:
r := 'Dieser Text kann nicht entschlüsselt werden';
3:
r := 'Sie haben keine Berechtigung';
4:
r := 'Fehler bei der Entschlüsselung';
else
r := 'Unbekannter Fehler';
end;
ShowMessage(r);
end;
//---------------------------------------------------------------------
// 4.Text mittels Tabelle verschlüsseln
// Getestet mit D2010 unter W7
// Eine simple Art der Verschlüsselung. Allerdings kann das Ergebnis über
// die Häufigkeit der auftretenden Zeichen geknackt werden. Reicht aber allemal
// aus, Text für andere Computer-User unleserlich zu machen. Die Zeichen in der
// Tabelle müssen natürlich nicht in der Reihenfolge stehen wie im Beispiel.
// Logischerweise braucht man für Ver- und Entschlüsselung die gleiche Tabelle.
// Beim ersten Durchlauf wird verschlüsselt, beim nächsten wieder entschlüsselt.
const
Tabelle = #10#32#13#9 +
'(+.%ßaÄäBbCcDdEeFfGgHhIiJjKkLlMmNnOoÖöPp=?-/;,!:*' +
'"_QqRrSsTtUuÜüVvWwXxYyZz0987654321A)';
function crypt(s: string): string;
var lg, ltab, stelle, such: integer;
begin
result := s;
lg := length(result);
if lg = 0 then exit;
ltab := length(Tabelle);
stelle := 1;
while stelle <= lg do begin
such := 1;
while (Tabelle[such] <> result[stelle]) and (such <= ltab) do inc(such);
if such <= ltab then result[stelle] := Tabelle[ltab - such + 1];
inc(stelle);
end;
end;
// Beispielaufruf
procedure TForm1.Button3Click(Sender: TObject);
begin
Memo1.text := crypt(Memo1.text);
end;
//---------------------------------------------------------------------
// 5. Text zu Zahlen verschlüsseln
// Getestet mit D2010 unter W7
// Um bei der Verschlüsselung zu vermeiden, dass Steuerzeichen entstehen
// (z.B. #0 als ungewolltes Stringende oder #13 als ungewollter Zeilenumbruch),
// werden die bereits verschlüsselten Buchstaben anschließend in eine
// Zahlenfolge umgewandelt, was man als zusätzliche Verschlüsselung ansehen
// kann. Allerdings ist der verschlüsselte String dreimal länger als das
// Original.
const
passwort = '1#-5ab8.*Z1'; // oder sonstwas
var
sss: string;
function verschluessele(zuverschluesseln, schluessel: string): string;
var x, y, lg: integer;
begin
result := '';
try
if length(zuverschluesseln) > 0 then begin
y := 1;
lg := length(schluessel);
for x := 1 to length(zuverschluesseln) do begin
result := result + formatfloat('000', ord(zuverschluesseln[x])
xor ord(schluessel[y]));
if y = lg then y := 1
else inc(y);
end;
end;
except result := ''; end;
end;
function entschluessele(zuentschluesseln, schluessel: string): string;
var x, y, lg: integer;
begin
result := '';
try
lg := length(zuentschluesseln);
if (lg > 0) and (lg mod 3 = 0) then begin
y := 1;
while y < lg do begin
result := result + chr(strtoint(copy(zuentschluesseln, y, 3)));
inc(y, 3);
end;
y := 1;
lg := length(schluessel);
for x := 1 to length(result) do begin
result[x] := chr(ord(result[x]) xor ord(schluessel[y]));
if y = lg then y := 1
else inc(y);
end;
end;
except result := ''; end;
end;
// Beispielaufruf
procedure TForm1.Button5Click(Sender: TObject);
begin
sss := verschluessele(Edit1.Text, passwort);
// showmessage(sss);
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
sss := entschluessele(sss, passwort);
// showmessage(sss);
end;
//---------------------------------------------------------
// 6. Verschlüsselung plus Zufall
// Getestet mit D2010 unter W7
// Der folgende Code arbeitet unter Zuhilfenahme des Zufallsgenerators.
// Der selbe Text liefert jedesmal ein anderes Teilergebnis, wenn er mit dem
// selben Schlüssel neu codiertt wird. Der verschlüsselte String wird
// doppelt so lang wie das Original.
function verschl(txt, schl: string): string;
var x, y, lg, n: integer;
begin
result := '';
lg := length(schl);
y := 1;
randomize;
for x := 1 to length(txt) do begin
n := (byte(txt[x]) xor byte(schl[y])) or
(((random(32) shl 8) and 15872) or 16384);
if lo(n) < 32 then n := n or 384;
if y = lg then y := 1
else inc(y);
result := result + chr(lo(n)) + chr(hi(n));
end;
end;
function entschl(txt, schl: string): string;
var x, y, lg, n: integer;
begin
if not odd(length(txt)) then begin
result := '';
lg := length(schl);
y := 1;
x := 1;
while x < length(txt) do begin
n := (byte(txt[x]) or (byte(txt[x + 1]) shl 8));
if n and 256 > 0 then n := n and 127
else n := n and 255;
result := result + chr(n xor byte(schl[y]));
if y = lg then y := 1
else inc(y);
inc(x, 2);
end;
end else result := txt;
end;
// Beispielaufruf
const schlssl = 'h*09mÖ-X#z&5%A@+0';
procedure TForm1.Button1Click(Sender: TObject);
begin
edit1.text := verschl(edit1.text, schlssl);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
edit1.text := entschl(edit1.text, schlssl);
end;
//---------------------------------------------------------
// 7. Variante von "3Z" für Unicode
// Getestet mit D2010 unter Win10
// Simple Variante der XOR-Verschlüsselung.
// Wenn ein bereits verschlüsselter Text nochmals verschlüsselt wird,
// kommt es auch hier zu Verlusten.
function VE3ZX(txt, schl: string; was: boolean): string;
var
i, z, x: integer;
a: array [0 .. 2] of integer;
begin
if length(schl) = 3 then
begin
result := '';
z := ord(was) * 2 - 1;
x := 0;
for i := 0 to 2 do
a[i] := ord(schl[i + 1]) - 31;
for i := 1 to length(txt) do
begin
result := result + chr((ord(txt[i]) + a[x] * z));
inc(x);
if x > 2 then
x := 0;
end;
end
else
result := txt;
end;
// Verschlüsseln
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.text := VE3ZX(Memo1.text, 'ö!A', true);
end;
// Entschlüsseln
procedure TForm1.Button2Click(Sender: TObject);
begin
Memo1.text := VE3ZX(Memo1.text, 'ö!A', false);
end;
//---------------------------------------------------------
// 8. Textdatei-Verschlüsselung mit Vorbehandlung
// Getestet mit D2010 unter W7
// Hiermit können Texte (Textdateien) verschlüsselt werden, wobei
// zunächst Buchstabenkombinationen durch Einzelzeichen ersetzt werden.
// Wichtig ist, dass im Array #10 und #13 an der richtigen Stelle stehen
// und dass das Array nicht mehr als 31 Elemente hat.
const
min = 1;
max = 31;
var
pwx: string = '#Mein Passwort#';
aos: array[min..max] of string =
('heit', 'keit', 'ung', 'le', 'ch', 'be', 'ei', 'em', 'ck', #10,
'ie', 'eu', #13, 'tt', 'ff', 'en', 'nn', 'gg', 'eh', 'ne', 'ig',
're', 'oh', 'an', 'la', 'mm', 'li', 'ss', 'er', 'au', 'he');
function verschl(txt, schl: string): string;
var
x, y, lg, n: integer;
begin
result := '';
if txt = '' then exit;
for x := min to max do
txt := stringreplace(txt, aos[x], chr(x), [rfreplaceall]);
lg := length(schl);
y := min;
randomize;
for x := min to length(txt) do begin
n := (byte(txt[x]) xor byte(schl[y])) or
(((random(32) shl 8) and 15872) or 16384);
if lo(n) < 32 then n := n or 384;
if y = lg then y := min
else inc(y);
result := result + chr(lo(n)) + chr(hi(n));
end;
end;
function entschl(txt, schl: string): string;
var
x, y, lg, n: integer;
begin
result := '';
if txt = '' then exit;
lg := length(schl);
y := min;
x := min;
while x < length(txt) do begin
n := (byte(txt[x]) or (byte(txt[succ(x)]) shl 8));
if n and 256 > 0 then n := n and 127
else n := n and 255;
result := result + chr(n xor byte(schl[y]));
if y = lg then y := min
else inc(y);
inc(x, 2);
end;
for x := min to max do
result := stringreplace(result, chr(x), aos[x], [rfreplaceall]);
end;
// Beispiel:
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.lines.loadfromfile('c:\Test.txt');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Memo2.Text := verschl(Memo1.Text, pwx);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Memo3.Text := entschl(Memo2.Text, pwx);
end;
//---------------------------------------------------------
// 9. Ganz simple Textdatei-Verschlüsselung
// Getestet mit D2010 unter W7
// Das älteste bekannte militärische Verschlüsselungsverfahren wurde von den Spartanern
// bereits vor mehr als 2500 Jahren angewendet. Zur Verschlüsselung diente ein (Holz-)Stab
// mit einem bestimmten Durchmesser (Skytale). Um eine Nachricht zu verfassen, wickelte der
// Absender einen Streifen wendelförmig um die Skytale, schrieb die Botschaft längs des
// Stabs auf das Band und wickelte es dann ab. Das Band ohne den Stab wird dem Empfänger
// überbracht. Fällt das Band in die falschen Hände, so kann die Nachricht nicht gelesen
// werden, da die Buchstaben scheinbar willkürlich auf dem Band angeordnet sind. Der
// richtige Empfänger des Bandes konnte die Botschaft mit einer identischen Skytale
// (einem Stab mit dem gleichen Durchmesser) lesen. Der Durchmesser des Stabes ist somit
// der geheime Schlüssel bei diesem Verschlüsselungsverfahren.
// Der Code empfindet das Verfahren nach, wobei die Variable "Diameter" den Stab-Durchmesser
// repräsentiert und Sender sowie Empfänger bekannt sein muss. Der Wert muss mindestens
// 2 betragen.
var
Diameter: Word;
function Skytale(const txt: String; out upshot: String): Byte;
var
lg, i, st, x: Integer;
hlp, s: string;
begin
try
lg := Length(txt);
if lg = 0 then
begin
Result := 1;
exit;
end;
if Diameter > lg div 2 then
begin
Result := 2;
exit;
end;
if Diameter < 2 then
begin
Result := 3;
exit;
end;
if odd(lg) then
begin
s := txt + #32;
inc(lg);
end
else
s := txt;
upshot := '';
st := Diameter;
for i := 1 to lg do
begin
x := ord(s[st]);
if x = 255 then
x := 31;
hlp := chr(x + 1);
upshot := upshot + hlp;
inc(st, Diameter);
if st > lg then
st := st - succ(lg);
if st < 1 then
st := Diameter;
end;
s := '';
Result := 0;
except
Result := 255;
end;
end;
function SkytaleInterpret(const txt: String; out upshot: String): Byte;
var
lg, st, i, x: Integer;
begin
try
lg := Length(txt);
if lg = 0 then
begin
Result := 1;
exit;
end;
if (Diameter > lg div 2) or (Diameter < 2) then
begin
Result := 2;
exit;
end;
st := Diameter;
upshot := txt;
for i := 1 to lg do
begin
x := pred(ord(txt[i]));
if x = 31 then
x := 255;
upshot[st] := chr(x);
inc(st, Diameter);
if st > lg then
st := st - succ(lg);
if st < 1 then
st := Diameter;
end;
Result := 0;
except
Result := 255;
end;
end;
// --- Beispielaufrufe ---
// Verschlüsseln
procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
b: Byte;
begin
Screen.Cursor := crHourGlass;
Button1.Enabled := False;
Application.ProcessMessages;
Memo1.Lines.BeginUpdate;
// Memo1.Text:='Das ist ein Test';
Memo1.Lines.LoadFromFile('C:\test.txt');
Diameter := 7; // z.B.
b := Skytale(Memo1.Text, s);
case b of
0:
Memo1.Text := s;
1:
Memo1.Text := 'Keinen Text zum Verschlüsseln gefunden';
2:
Memo1.Text := 'Diameter im Verhältnis zum Text zu groß';
3:
Memo1.Text := 'Diameter muss mindestens 2 sein';
else
Memo1.Text := 'Unerwarteter Fehler';
end;
s := '';
Memo1.Lines.EndUpdate;
Screen.Cursor := crDefault;
Button1.Enabled := True;
end;
// Entschlüsseln
procedure TForm1.Button2Click(Sender: TObject);
var
b: Byte;
s: string;
begin
Button2.Enabled := False;
Application.ProcessMessages;
Diameter := 7;
b := SkytaleInterpret(Memo1.Text, s);
case b of
0:
Memo2.Text := s;
1:
Memo2.Text := 'Keinen Text zum Entschlüsseln gefunden';
2:
Memo2.Text := 'Falscher Wert für Diameter';
else
Memo2.Text := 'Unerwarteter Fehler';
end;
s := '';
Button2.Enabled := True;
end;
//---------------------------------------------------------
// 10. Textdatei-Verschlüsselung mit Datum und Prüfsumme
// Getestet mit Delphi 10.4 unter W11
// Im Ursprungsschreiben muss ein Datum abgebildet sein, welches dann automatisch ermittelt
// wird. Dieses Datum muss dem Empfänger bekannt sein, denn er muss es vor dem Entschlüsseln
// in Edit2 Eingeben. In Edit1 muss von beiden ein Zahlen-Key zwischen 123 und 123456 eingegeben
// werden, der aus Sicherheitsgründen keine Nullen und direkt nebeneinander keine doppelte Ziffern
// enhalten darf. Auf der Form befinden sich 1 TRichEdit, 3 TButton und 2 TEdit.
|
|
Zugriffe seit
6.9.2001 auf Delphi-Ecke |