Hi,
Nach der Lektüre von "Digital Fortress" (Diabolus) Habe ich mich längere Zeit gefragt, was mit einer "rotating cleartext function" gemeint sein könnte (sofern sie existiert). (Ob Dan Brown selbst eine Idee hat wie soetwas gehen könnte?)
Nach einiger Überlegung stieß ich auf eine (mir völlig neue) Idee der Verschlüsselung.
Hierbei generiere ich zunächst eine (peudo-)zufällige Index-Datei zu einer Wortliste.
Dann ersetze ich nach dem in der Index-Datei angegebenen Schema alle Wörter im Ausgangstext (und beim dekodieren wieder zurück).
"Passphrase" ist bisher lediglich die Index-Datei sowie die Wortliste. Ob es sich lohnt (und wie es gehen würde) einen zusätzlichen Passphrase im üblichen Sinne einzubauen, weiss ich (noch?) nicht.
Naja, genug der Theorie, hier etwas Code:
Delphi-Quellcode:
TForwarding = packed record
x: Int64;
y: Int64;
end;
TForwardings = array of TForwarding;
THeader = packed record
FileSize: Int64;
Datas: Int64;
end;
TEntry = record
PointSucc: Boolean;
PointPrec: Boolean;
Succ: Int64;
Prec: Int64;
Index: Int64;
end;
TEntries = array of TEntry;
TForwardings ist der eigentliche Inhalt der Index-Datei. Der Index im Array entspricht dem Index in der Wortliste, X ist der Vorgänger und Y der Nachfolger.
TEntries ist ein Array zum Internen Generieren der Forwardings.
THeader wird vorne in die Datei geschrieben. Hat zwar noch keine wichtige Funktion, aber es ist ganz praktisch im vornherein zu wissen wie viele Forwardings man denn nu hat^^
Die Wortliste verwalte ich ganz einfach in einer TStringList.
Das ganze habe ich in eine Klasse geknallt...
CallPrg, CallInitPrg und CallStatus sind Events der Klasse um den Fortschritt und Status-Texte auszugeben...
Nun zum Generieren des Indexes:
Delphi-Quellcode:
procedure TWordEncryption.GenerateIndex;
var FS: TFileStream;
Head: THeader;
FW: TForwarding;
i: Integer;
E: TEntries;
S: Int64;
begin
CallPrg(0,aGenerate);
CallInitPrg((WL.Count-1) div 1000,aGenerate);
CallStatus('Übertrage Wortliste...',aGenerate);
SetLength(E,WL.Count);
for i:=0 to WL.Count-1 do
begin //Erstmal alles reinkopieren
E[i].PointSucc:=False;
E[i].PointPrec:=False;
E[i].Index:=i;
E[i].Succ:=0;
E[i].Prec:=0;
end;
CallStatus('Generiere Index-Datei...',aGenerate);
for i:=0 to Length(E)-1 do
begin //Nochmal alles durchlaufen
if (i mod 1000 = 0) then
begin
CallPrg(i,aGenerate);
end;
S:=Random(Length(E)); //Und zufällig ein Element suchen was noch keinen Vorgänger hat.
while (E[S].PointPrec) do S:=Random(Length(E));
E[i].PointSucc:=True; //Wenn man dann eins hat die "Zeiger" (=Indexe) richtig setzen
E[S].PointPrec:=True; //Und die Status-Bools setzen
E[S].Prec:=E[i].Index;
E[i].Succ:=E[S].Index;
end;
FS:=TFileStream.Create(FIndexFile,fmShareExclusive or fmOpenWrite);
Head.FileSize:=Length(WL.Text); //Dann bastlen wir uns noch schnell nen Header
Head.Datas:=WL.Count;
FS.Size:=0;
FS.Position:=0;
FS.Write(Head,SizeOf(THeader));
CallStatus('Speichere Index-Datei...',aGenerate);
for i:=0 to Length(E)-1 do
begin //...und schreiben alles in die Datei
FW.x:=E[i].Prec;
FW.y:=E[i].Succ;
FS.Write(FW,SizeOf(TForwarding));
end;
FS.Free;
CallStatus('Bereit.',aGenerate);
CallPrg(0,aGenerate); //Fertig
end;
Nun hat man eine Index-Datei...Soweit so gut.
Nun kommt es zum Kodieren bzw zum Dekodieren.
Delphi-Quellcode:
TStringDynArray = array of String;
TCodeDirection = (cdEncode,cdDecode);
function TWordEncryption.CodeIt(Src, Passphrase: String; T: TCodeDirection): String;
/*
Src wird (De-)Kodiert
Passphrase ist zZ noch ohne Funktion
T ist die Richtung (cdEncode oder cdDecode)
*/
var i,j,k: Integer;
F: TForwardings;
Head: THeader;
FS: TFileStream;
D: TStringDynArray;
begin
CallPrg(0,aCode);
Result:='';
CallStatus('Lade Index-Datei...',aCode);
FS:=TFileStream.Create(FIndexFile,fmShareExclusive or fmOpenRead);
FS.Read(Head,SizeOf(THeader)); //Erstmal wieder auspacken
SetLength(F,Head.Datas);
for i:=0 to Head.Datas-1 do
FS.Read(F[i],SizeOf(TForwarding));
FS.Free; //Nu ist alles in F drin
CallStatus('Kodiere Text...',aCode);
D:=Explode(' ',Src); //In die Einzel-Wörter Splitten
for i:=0 to Length(D)-1 do
begin
CallPrg(i,aCode);
j:=WL.IndexOf(D[i]); //Den Index des Wortes holen
if (j<0) or (j>=WL.Count) then
Result:=Result+D[i]+' ' //Wenn Wort nicht in der Wortliste ist, dann schreiben wirs einfach wieder so rein
else if T=cdEncode then
begin //Kodieren
for k:=1 to i do
j:=F[j].y; //Wir nehmen und ein i-mal den Nachfolger
Result:=Result+WL[F[j].y]+' ';
end
else if T=cdDecode then
begin //Dekodieren
for k:=1 to i do
j:=F[j].x; //Wir nehmen und ein i-mal den Vorgänger
Result:=Result+WL[F[j].x]+' ';
end;
end;
CallPrg(0,aCode); //Fertig.
CallStatus('Bereit.',aCode);
end
Ja und das war es eigentlich auch schon
Nun meine Frage:
Wie sicher ist so eine "Verschlüsselung"?
Durch herkömmliche Brute-Force Attacken ist sie ja nun kaum zu verwunden, da sie beim richtigen Text keine signifikanten unterschiede zu einer falschen version aufweist. (Es ist immer, mehr oder weniger, sinnvoller Text. Daher bräuchte es wirklich eine Brute-Force welche auf Satzzusammenhang prüft....).
Ich hänge mal
a) die
Unit + Beispielprogramm und
b) eine Wortliste an
damit habe ich einen Text verschlüsselt.
Dier Kodierte Fassung ist:
"Fadensonde Disziplinargericht Duschnik Puppenwagen . zugemacht Schaufensterwettbewerb Schriftart umsatzlos !"
kann es wer entschlüsseln?