10. Javascript: Texteinbettung in Quatschcode
Diese Abhandlung beschäftigt sich mit der Einbettung von Text in
Quatschcode im Rahmen einer eher neuarigen Verschlüsselungstechnik, die
alleine schwach ist, aber integriert in eine reguläre Verschlüsselung
den Standort von Buchstaben bis zur unendlichkeit verschleiert.
Sie können das in der Demo nachvollziehen, in dem Sie die Demo
mit ihrem Browser bei aktivierten Javascript öffnen und den
Text "Optionen einblenden/ausblenden" betätigen.
Geben sie dann einen Text und einen beliebig langen Passwortsatz oder
Wort ein und betätigen sie dann den Button Quatschcode.
Zum dekodieren, also den Text wieder in seine Ursprungsform zu bringen,
drücken Sie den danebenliegenden Button Quatschreturn.
Was passierte? Richtig, die Buchstaben und Leerzeichen werden in
Dreierblöcken eingebettet, wobei die Stelle des Buchstabens im
Dreierblock von der Buchstabenkombination im Passwort abhängig
ist.
Ich stelle im folgenden das Javascript der Funktion vor und wir gehen
dann den Code einmal im Schnelldurchlauf vor.
function enc15() {
mpwstz=document.changeForm.pass.value;
if (mpwstz== "")
var mpwstz=document.getElementById("masterpass").innerHTML;
msatz = document.changeForm.dialog.value;
manton=mpwstz;
while (mpwstz.length < msatz.length) {
mpwstz+= manton
}
treffer ="";
wbstb = "";
for (myl=0; myl<msatz.length; myl++)
{
mpsw = eval("mpwstz.charAt(" +myl+")");
if (mpsw == "") wbstb = 0;
if (mpsw == "a") wbstb = 1;
if (mpsw == "b") wbstb = 2;
if (mpsw == "c") wbstb = 0;
if (mpsw == "d") wbstb = 1;
if (mpsw == "e") wbstb = 2;
if (mpsw == "f") wbstb = 0;
if (mpsw == "g") wbstb = 1;
if (mpsw == "h") wbstb = 2;
if (mpsw == "i") wbstb = 0;
if (mpsw == "j") wbstb = 1;
if (mpsw == "k") wbstb = 2;
if (mpsw == "l") wbstb = 0;
if (mpsw == "m") wbstb = 1;
if (mpsw == "n") wbstb = 2;
if (mpsw == "o") wbstb = 0;
if (mpsw == "p") wbstb = 1;
if (mpsw == "q") wbstb = 2;
if (mpsw == "r") wbstb = 0;
if (mpsw == "s") wbstb = 1;
if (mpsw == "t") wbstb = 2;
if (mpsw == "u") wbstb = 0;
if (mpsw == "v") wbstb = 1;
if (mpsw == "w") wbstb = 2;
if (mpsw == "x") wbstb = 0;
if (mpsw == "y") wbstb = 1;
if (mpsw == "z") wbstb = 2;
if (mpsw == "0") wbstb = 0;
if (mpsw == "1") wbstb = 1;
if (mpsw == "2") wbstb = 2;
if (mpsw == "3") wbstb = 0;
if (mpsw == "4") wbstb = 1;
if (mpsw == "5") wbstb = 2;
if (mpsw == "6") wbstb = 0;
if (mpsw == "7") wbstb = 1;
if (mpsw == "8") wbstb = 2;
if (mpsw == "9") wbstb = 0;
if (mpsw == ".") wbstb = 1;
if (mpsw == "(") wbstb = 2;
if (mpsw == "A") wbstb = 2;
if (mpsw == "B") wbstb = 1;
if (mpsw == "C") wbstb = 0;
if (mpsw == "D") wbstb = 2;
if (mpsw == "E") wbstb = 1;
if (mpsw == "F") wbstb = 0;
if (mpsw == "G") wbstb = 2;
if (mpsw == "H") wbstb = 1;
if (mpsw == "I") wbstb = 0;
if (mpsw == "J") wbstb = 2;
if (mpsw == "K") wbstb = 1;
if (mpsw == "L") wbstb = 0;
if (mpsw == "M") wbstb = 2;
if (mpsw == "N") wbstb = 1;
if (mpsw == "O") wbstb = 0;
if (mpsw == "P") wbstb = 2;
if (mpsw == "Q") wbstb = 1;
if (mpsw == "R") wbstb = 0;
if (mpsw == "S") wbstb = 2;
if (mpsw == "T") wbstb = 1;
if (mpsw == "U") wbstb = 0;
if (mpsw == "V") wbstb = 2;
if (mpsw == "W") wbstb = 1;
if (mpsw == "X") wbstb = 0;
if (mpsw == "Y") wbstb = 2;
if (mpsw == "Z") wbstb = 1;
if (mpsw == " ") wbstb = 0;
if (mpsw == ")") wbstb = 2;
if (mpsw == ",") wbstb = 1;
if (mpsw == "?") wbstb = 0;
if (mpsw == "\"") wbstb = 2;
if (mpsw == "/") wbstb = 1;
if (mpsw == "+") wbstb = 0;
if (mpsw == "-") wbstb = 2;
if (mpsw == "=") wbstb = 1;
if (mpsw == "^:") wbstb = 0;
if (mpsw == "!") wbstb = 2;
if (mpsw == "§") wbstb = 1;
alternatens = Math.floor((Math.random() * 76) + 1);
bstswhl = eval("msatz.charAt(" +myl+")");
if (wbstb == 0) {
treffer+= bstswhl ;
} else {
treffer+= change1[alternatens][1] ;
}
if (wbstb == 1) {
treffer+= bstswhl ;
} else {
treffer+= change1[alternatens][2] ;
}
if (wbstb == 2) {
treffer+= bstswhl ;
} else {
treffer+= change1[alternatens][3] ;
}
mpsw = "";
wbstb = "";
bstswhl = "";
alternatens = "";
}
document.changeForm.dialog.value = treffer;
}
Erklärung der ersten Zeilen:
function enc15() {
mpwstz=document.changeForm.pass.value;
if (mpwstz== "")
var mpwstz=document.getElementById("masterpass").innerHTML;
msatz = document.changeForm.dialog.value;
manton=mpwstz;
while (mpwstz.length < msatz.length) {
mpwstz+= manton
}
Die Funtion heßt also enc15() und nach der geschweiften Klammer bis zur
letzten geschweiften Klammer ist dieses die Funktion. Ausgelöst wird
die Funktion durch einen Button im HTML-Bereich.
Die nächsten Zeilen dienen der Ziehung des Passwortsatze: Tragen Sie
einen Passwortsatz oder ein Wort ein, dann wird in der Variable pwssatz
dieser Text abgespeichert. Wenn nicht, dann wird ein verborgener Satz
im HTML-Document verwendet: Das nennt man Fallback-Funktion.
Danach wird in der Variable satz der Text aufgenommen, den Sie
einbetten wollen.
Am Ende wird noch eine Variable geschaffen, die den Passwortsatz
enthält.
Damit sind erst einmal alle relevanten Texte für die folgende
Bearbeitung dem Skript verfügbar: Das ist das Geheimnis von
Javascript: Sie müssen alle Daten erst einmal dem Skript in
verständlicher Form vorlegen...Der Rest ist syntax...
msatz = document.changeForm.dialog.value;
manton=mpwstz;
while (mpwstz.length < msatz.length) {
mpwstz+= manton
}
In der while-Schleife sorge ich nun dafür, dass der Passwortsatz auf
jedenfall länger wird als der Text, den Sie eingeben.
Dazu addiere ich den Passwortsatz mit dem Passwortsatz so lange ( mpwssatz+= manton) , bis der Passwortsatz länger
(mpwstz.length < msatz.length) ist als der zu verschlüsselnde Text.
Deshalb brauche ich auch die Variable Anton, weil Javascript bockig reagiert, wenn man allein den mpwstz mit sich selbst addiert.
Das muss ich machen, damit ich für jeden Buchstaben des Textes einen
Bezugsbuchstaben habe, der die Position im Dreierblock bestimmt.
Die folgende For-Schleife orientiert sich nämlich an der Länge des eingegebenen Textes und nicht des Passwortes!
treffer ="";
wbstb = "";
for (myl=0; myl<msatz.length; myl++)
{
mpsw = eval("mpwstz.charAt(" +myl+")");
if (mpsw == "") wbstb = 0;
if (mpsw == "a") wbstb = 1;
if (mpsw == "b") wbstb = 2;
if (mpsw == "c") wbstb = 0;
In der For-Schleife kommen zwei neue Variablen vor, die ich als leblose
Hülle erst einmal als leer definiere: Die werden dann in der
For-Schleife mit Buchstaben gefüllt....
Die For Schleife zieht sich also Zeichen für Zeichen mit Null beginnend, bis Sie kleiner als die Satzlänge ist (for (myl=0; myl<msatz.length; myl++)) .
Das ist so richtig, weil Javascript mit Null beginnt zu zählen, während msatz.length
Bei eins beginnt zu zählen. Das Wort "das" hat also 3 Buchstaben, bei
Null beginnend zu zählen ist 0=d, 1=a und 2=s. Somit sind alle
Buchstaben erfasst!
mpsw = eval("mpwstz.charAt(" +myl+")");
Beim Password wird parallel der entsprechende Buchstabe gezogen (myl), welches der Zahl des Buchstabens der For-Schleife entspricht.
Wir haben bei einem Durchlauf also erstmal einen Buchstaben vom
Password gezogen, welcher im Folgenden in eine Zahl umgewandelt wird
if (mpsw == "") wbstb = 0;
if (mpsw == "a") wbstb = 1;
if (mpsw == "b") wbstb = 2;
if (mpsw == "c") wbstb = 0;
Das ist nur ein kleiner Auszug, um den Sinn zu verstehen: Wenn der
gezogene Buchstabe gar nichts entspricht, dann ist die Variable wbstb,
die außerhalb der For-Schleife zuvor als leere Hülle eingeführt wird
eine 0. Das ist der Fallback, wenn der Buchstabe nicht definiert ist.
Ansonsten bei klein a eine 1, bei klein b eine 2 oder bei klein c eine
3. Ich definiere also jede erdenkliche Möglichkeit bis zum Leerzeichen
mit einer Zahl, die 0,1 oder 2 entspricht.
Das wird jetzt happig:
alternatens = Math.floor((Math.random() * 76) + 1);
bstswhl = eval("msatz.charAt(" +myl+")");
if (wbstb == 0) {
treffer+= bstswhl ;
} else {
treffer+= change1[alternatens][1] ;
}
if (wbstb == 1) {
treffer+= bstswhl ;
} else {
treffer+= change1[alternatens][2] ;
}
if (wbstb == 2) {
treffer+= bstswhl ;
} else {
treffer+= change1[alternatens][3] ;
}
alternatens = Math.floor((Math.random() * 76) + 1); ist verständlich eine Zufallszahl von 1-76.
bstswhl = eval("msatz.charAt(" +myl+")"); Wir
definieren innerhalb der Schleife nun den dazugehörigen Buchstaben oder
das Zeichen innerhalb der Forschleife unter Verwendung der Variable
myl. Die kann natürlich beliebig oft verwendet werden.
if (wbstb == 0) {
treffer+= bstswhl ;
} else {
treffer+= change1[alternatens][1] ;
}
Die if else Konstruktion sagt nichts anderes aus als in schlechten deutsch:
Wenn der Passwortbuchstabe, der in den vorherigen Schritten
in eine 0 umgewandelt wurde ist, dann ist die Variable Treffer mit dem
unverschlüsselten Originalzeichen zu besetzen, sonst bediene dich
(else) aus einem mehrdimensionalen Array im Javascript aus der Tabelle
change1 und ziehe einen zufälligen Buchstaben [alternatens] aus der ersten Reihe des mehrfachen Array [1] .
Das Array hat 76 Buchstaben (1-76). Es steht dort also Quatschcode oder
der Buchstabe aus dem Text. Dieselbe Abfrage wird dreimal
hintereinander gemacht: Eben mit 0,1 und 2.
Eine von den drei abfragen haut also hin, bei Zwei Abfragen jedoch
entsteht ein durch Zufall generierter Buchstabe, bei einer Abfrage der
eigentlich richtige Treffer, wo dann der richtige Buchstabe steht.
Dadurch wird der Buchstabe bzw. der Text verdreifacht, weil die
For-Schleife, in der dieser Prozess abläuft sich immer wiederholt.
So bekommt man bei jedem Durchgang drei Buchstaben mehr in die Variable
treffer, abhängig von einem Password und das ist doch tricky?
Die Variable treffer wird am Ende wieder im Dokument ausgegeben, aber wie kriegt man das wieder in korrekten Text zurück?
Ich beschreibe die Funktion kürzer, weil vieles gleich ist und wer bis
hierher das nicht verstaden hat, der wird den Rest auch nicht
verstehen:
function dec15() {
rpws=document.changeForm.pass.value;
if (rpws== "")
var rpws=document.getElementById("masterpass").innerHTML;
rmstz = document.changeForm.dialog.value;
rrmntn=rpws;
vers=rmstz.length;
ausgleich=rmstz.length-1;
while (rpws.length < ausgleich) {
rpws+= rrmntn
}
rtreffer = "";
rntreffer = "";
rbstb = "";
add = 0;
for (rmyl=0; rmyl<vers; rmyl++)
{
rmpsw = eval("rpws.charAt(" +rmyl+")");
if (rmpsw == "") rbstb = 0;
if (rmpsw == "a") rbstb = 1;
if (rmpsw == "b") rbstb = 2;
if (rmpsw == "c") rbstb = 0;
if (rmpsw == "d") rbstb = 1;
if (rmpsw == "e") rbstb = 2;
if (rmpsw == "f") rbstb = 0;
if (rmpsw == "g") rbstb = 1;
if (rmpsw == "h") rbstb = 2;
if (rmpsw == "i") rbstb = 0;
if (rmpsw == "j") rbstb = 1;
if (rmpsw == "k") rbstb = 2;
if (rmpsw == "l") rbstb = 0;
if (rmpsw == "m") rbstb = 1;
if (rmpsw == "n") rbstb = 2;
if (rmpsw == "o") rbstb = 0;
if (rmpsw == "p") rbstb = 1;
if (rmpsw == "q") rbstb = 2;
if (rmpsw == "r") rbstb = 0;
if (rmpsw == "s") rbstb = 1;
if (rmpsw == "t") rbstb = 2;
if (rmpsw == "u") rbstb = 0;
if (rmpsw == "v") rbstb = 1;
if (rmpsw == "w") rbstb = 2;
if (rmpsw == "x") rbstb = 0;
if (rmpsw == "y") rbstb = 1;
if (rmpsw == "z") rbstb = 2;
if (rmpsw == "0") rbstb = 0;
if (rmpsw == "1") rbstb = 1;
if (rmpsw == "2") rbstb = 2;
if (rmpsw == "3") rbstb = 0;
if (rmpsw == "4") rbstb = 1;
if (rmpsw == "5") rbstb = 2;
if (rmpsw == "6") rbstb = 0;
if (rmpsw == "7") rbstb = 1;
if (rmpsw == "8") rbstb = 2;
if (rmpsw == "9") rbstb = 0;
if (rmpsw == ".") rbstb = 1;
if (rmpsw == "(") rbstb = 2;
if (rmpsw == "A") rbstb = 2;
if (rmpsw == "B") rbstb = 1;
if (rmpsw == "C") rbstb = 0;
if (rmpsw == "D") rbstb = 2;
if (rmpsw == "E") rbstb = 1;
if (rmpsw == "F") rbstb = 0;
if (rmpsw == "G") rbstb = 2;
if (rmpsw == "H") rbstb = 1;
if (rmpsw == "I") rbstb = 0;
if (rmpsw == "J") rbstb = 2;
if (rmpsw == "K") rbstb = 1;
if (rmpsw == "L") rbstb = 0;
if (rmpsw == "M") rbstb = 2;
if (rmpsw == "N") rbstb = 1;
if (rmpsw == "O") rbstb = 0;
if (rmpsw == "P") rbstb = 2;
if (rmpsw == "Q") rbstb = 1;
if (rmpsw == "R") rbstb = 0;
if (rmpsw == "S") rbstb = 2;
if (rmpsw == "T") rbstb = 1;
if (rmpsw == "U") rbstb = 0;
if (rmpsw == "V") rbstb = 2;
if (rmpsw == "W") rbstb = 1;
if (rmpsw == "X") rbstb = 0;
if (rmpsw == "Y") rbstb = 2;
if (rmpsw == "Z") rbstb = 1;
if (rmpsw == " ") rbstb = 0;
if (rmpsw == ")") rbstb = 2;
if (rmpsw == ",") rbstb = 1;
if (rmpsw == "?") rbstb = 0;
if (rmpsw == "\"") rbstb = 2;
if (rmpsw == "/") rbstb = 1;
if (rmpsw == "+") rbstb = 0;
if (rmpsw == "-") rbstb = 2;
if (rmpsw == "=") rbstb = 1;
if (rmpsw == "^:") rbstb = 0;
if (rmpsw == "!") rbstb = 2;
if (rmpsw == "§") rbstb = 1;
alter = add;
rtreffer = alter + rbstb;
rbstswhl = eval("rmstz.charAt(" +rtreffer+")");
if (1 != 5) rntreffer+= rbstswhl;
rmpsw = "";
rtreffer = "";
rbstswhl = "";
alter = "";
rbstb = "";
add = add + 3;
}
document.changeForm.dialog.value = rntreffer;
}
Jetzt wir es richtig schwer: Die Funktion wird mit dem Button im HTML-Dokument gestartet und die Variablen wieder gesetzt.
Die Variablen-Namen dürfen sich nicht mit den Namen der Variablen in
anderen Funktionen überschneiden - daran scheitern viele Profis, die
nach irgendwelchen Nomenklaturen arbeiten. Deshalb verwende ich auch
mehrere Buchstaben in for-Schleifen, bei großen Projekten hilfreich,
wenn alle einstelligen oder zweistelligen Variablen-Namen vergeben
werden.
Außerdem brauchen wir einen total anderen Denkansatz: In jedem Dreierblock ist also ein Buchstabe, den wir auswählen müssen.
Deshalb schaffe ich eine variable Namens add, die vor der Vorschleife
mit 0 definiert wird. Am Ende eines Durchgangs mit der Schleife wird
diese mit drei addiert.
Auf diese Art und Weise gehe ich dann auch immer einen Dreierblock im
eingebetteten Text durch: Im ersten Durchlauf will ich also 0,1,2
auswählen und weis von der Verschlüsselung her, das dort ein Treffer
besteht: Entweder an der Stelle 0,1,2 im Ersten Durchgang.
Also Frage ich wieder den Wert des ersten Buchstabens des Passwortes ab und erhalte eine 0,1 oder 2. ( rbstb)
Diese Zahl addiere ich mit add bzw. alter, die gleich add ist, aber
nochmals definiert werden muss - tut mir leid geht nicht anders..
Im ersten Durchlauf ist add also eine 0 und die wird mit 0, 1 oder 2 addiert (rtreffer = alter + rbstb;).
Danach der Treffer als Buchstabe aus dem Text gezogen (rbstswhl = eval("rmstz.charAt(" +rtreffer+")"); ).
if (1 != 5) rntreffer+= rbstswhl; hört
sich unsinnig an, aber um eine Addition von Text zu erreichen brauche
ich zwingend eine if-Konstruktion und 1 wird immer ungleich fünf sein
-:)
Mein Ziel wurde erreicht, ich habe in diesem Dreierblock die Stelle
ermittelt, wo der Buchstabe steht, wo kein Quatschcode steht.
In der letzten Zeile wird add unabhängig um drei erhöht (die Buchstaben 3,4,5 werden bearbeitet) und dasselbe Spiel beginnt:
Der Buchstabe vom Passworttext wird gezogen und in die entsprechende Zahl 0,1,2 umgewandelt.
Diese Zahl wird nun mit drei addiert, welches als Ergebnis eben 3,4
oder 5 ist - ein anderes Ergebnis ist nicht möglich. Diese Zahl wird
wieder in einen Buchstaben umgewandelt und der Buchstabe in der
Variable rntreffer aufgenommen....
Das letzte Problem ist die Länge des zu bearbeitenden Textes, den
könnte man über ein Drittel der Länge des ursprünglichen Textes
regeln, aber ich lasse die For Schleife eben durchlaufen und bei (rbstswhl = eval("rmstz.charAt(" +rtreffer+")"); )
gibt es dann im wahrsten Sinne keine Treffer mehr am Ende. Demzufolge
wird automatisch nichts mehr buchstabenmäßig addiert, dass läuft ins
Lehrer ohne Fehlermeldung.
Fazit
Die Einbettung von Tet in Quarkcode ist eine anspruchsvolle
Programmierung und ich löste das mit einem mehrdimensionalen Array und
einer Zufallszahl zur Generierung des Quatsch-Codes.
Die Vetreilung der Buchstaben löste ich in Dreierblöcken, die durch
eine if else-Abfrage mit umgewandelten Zahlen aus einem Passwortsatz
den Platz des Originaltextes bestimmen.
Dadurch kommt es zu einer unterschiedlichen Verteilung der Positionen in den Dreierblöcken.
Umgekehrt wird beim Dekodieren ein Dreierblock geschaffen,
in dem durch die umgewandelte Zahl aus dem Passwortsatz und einer
simplen Addition die Position des Buchstabens wieder bestimmt.
Der Quatschcode wird dabei ignoriert, genau wie das Array, aus dem der Quatschcode kam.
Drückt man den Kodierungsbutton zweimal, dann sind wir bei 9 Buchstaben
angtelangt, von dem 1 Buchstabe vom Originaltext stammt (Zum Dekodieren
zweimal den Returnbutton drücken).
Aus einer Seite Text wurden im o. a. Beispiel 9 Seiten: Javascript
schafft das locker. Wird dann dazwischen noch mit irgendeiner anderen
Funktion kodiert, dann ist das schon ein wenig schwerer knackbar -
So ist diese Funktion eine Killerfunktion, da der potentielle Angreifer
nicht über die Position der Buchstaben genau bescheid weiß.