diff --git a/Verschlüsselung/src/Enigma/Enigma.java b/Verschlüsselung/src/Enigma/Enigma.java new file mode 100644 index 0000000..03f0d83 --- /dev/null +++ b/Verschlüsselung/src/Enigma/Enigma.java @@ -0,0 +1,127 @@ +package Enigma; + +public class Enigma { + + // 5 Walzen (https://de.wikipedia.org/wiki/Enigma_(Maschine)#Aufbau) + private final String[] W = { + "EKMFLGDQVZNTOWYHXUSPAIBRCJ", + "AJDKSIRUXBLHWTMCQGZNPYFVOE", + "BDFHJLCPRTXVZNYEIWGAKMUSQO", + "ESOVPZJAYQUIRHXLNFTGKDCMWB", + "VZBRGITYUPSDNHLXAWMJQOFECK" + }; + + // 3 Umkehrwalzen (https://de.wikipedia.org/wiki/Enigma_(Maschine)#Aufbau) + private final String[] UKW = { + "EJMZALYXVBWFCRQUONTSPIKHGD", + "YRUHQSLDPXNGOKMIEBFZCWVJAT", + "FVPJIAOYEDRZXWGCTKUQSBNMHL" + }; + + private Walze[] w; + private Walze ukw; + private Steckbrett s; + + /** + * @param config Leerzeichen getrennter String: + * 1. Anzahl Walzen + * 2. Walzenkonfiguration jeweils: + * 2.1. Walzennummer (0-5) + * 2.2. Walzenring (0-25) + * 2.3. Walzenstellung (0-25) + * 3. Umkehrwalze (0-2) + * 4. Steckbrett, leerzeichengetrennt Buchstabenpaare + * + * Achtung: noch keine Fehlerbehandlung! Steckbrett -> Buchstaben dürfen nicht doppelt vorkommen! + */ + public Enigma(String config) { + String[] c = config.split(" "); + + int walzenanzahl = Integer.parseInt(c[0]); + + this.w = new Walze[walzenanzahl]; + + int i = 1; + for (int j = 0; j < walzenanzahl; j++) { + int walze = Integer.parseInt(c[i++]); + int ring = Integer.parseInt(c[i++]); + int stellung = Integer.parseInt(c[i++]); + + this.w[j] = new Walze(this.W[walze], ring, stellung); + } + + int ukw = Integer.parseInt(c[i++]); + this.ukw = new Walze(this.UKW[ukw], 0, 0); + + String s = ""; + for (int j = i; j < c.length; j++) { + if (j != i) s += " "; + s += c[j]; + } + + this.s = new Steckbrett(s); + } + + /** + * + * @param s + * @return + */ + public String crypt(String s) { + return this.crypt(s, true); + } + + /** + * ver- und entschlüsselt einen Text + * @param s String der verschlüsselt werden soll + * @param hidespecial sollen Zeichen, die keine Buchstaben sind ausgeblendet werden? + * @return ver- bzw. entschlüsselter Text + */ + public String crypt(String s, boolean hidespecial) { + String ret = ""; + + for (int i = 0; i < s.length(); i++) { + // einzelner Buchstabe aus Text + char c = s.toUpperCase().charAt(i); + + // wenn kein Buchstabe, dann ggf. überspringen oder unverschlüsselt übernehmen + if (c < 'A' || c > 'Z') { + if (!hidespecial) ret += c; + continue; + } + + // Steckbrett durchlaufen + c = this.s.in(c); + + // Walzen in Hinrichtung durchlaufen + for (int w = 0; w < this.w.length; w++) { + c = this.w[w].in(c); + } + + // Umkehrwalze durchlaufen + c = this.ukw.in(c); + + // Walzen in Rückrichtung durchlaufen + for (int w = this.w.length - 1; w >= 0; w--) { + c = this.w[w].out(c); + } + + // Steckbrett nochmals durchlaufen + c = this.s.in(c); + + // verschlüsselter Buchstabe an Ergebnis anhängen + ret += c; + + // Walzen weiter drehen + for (int w = 0; w < this.w.length; w++) { + if (!this.w[w].next()) break; + } + + // zur besseren Übersicht Leerzeichen einfügen + if (i % 5 == 4 && hidespecial) ret += ' '; + } + + return ret; + } + +} diff --git a/Verschlüsselung/src/Enigma/Start.java b/Verschlüsselung/src/Enigma/Start.java new file mode 100644 index 0000000..74c4367 --- /dev/null +++ b/Verschlüsselung/src/Enigma/Start.java @@ -0,0 +1,24 @@ +package Enigma; + +public class Start { + + public static void main(String[] args) { + + // 3 -> 3 Walzen + // 0 0 0 -> 1. Walze Nr 0, Ring 0, Ausgangsstellung 0 + // 2 0 0 -> 2. Walze Nr 2, Ring 0, Ausgangsstellung 0 + // 1 0 0 -> 3. Walze Nr 1, Ring 0, Ausgangsstellung 0 + // 0 -> Umkehrwalze Nr 0 + // AG EP QS XY ZD -> Steckfeldkonfiguration + String config = "3 0 0 0 2 0 0 1 0 0 0 AG EP QS XY ZD"; + + Enigma e = new Enigma(config); + System.out.println(e.crypt("Informatik ist Toll!", false)); + + // Zurück auf Ausgansposition + e = new Enigma(config); + // 2. Parameter false -> Sonderzeichen unverschlüsselt kopieren + System.out.println(e.crypt("WOQNWNRZGW XHU FKJD!", false)); + + } +} diff --git a/Verschlüsselung/src/Enigma/Steckbrett.java b/Verschlüsselung/src/Enigma/Steckbrett.java new file mode 100644 index 0000000..ccd61e9 --- /dev/null +++ b/Verschlüsselung/src/Enigma/Steckbrett.java @@ -0,0 +1,43 @@ +package Enigma; + +public class Steckbrett { + + private int[] vertauschung; + + /** + * Steckbrett anlegen + * @param v leerzeichengetrennte Buchstabenpaare, die vertauscht werden sollen, Großbuchstaben! Keine doppelten Buchstaben verwenden! + */ + public Steckbrett(String v) { + // Vertauschungs-Liste anlegen + this.vertauschung = new int[26]; + for (int i = 0; i < 26; i++) { + // Standardmäßig: keine Vertauschung + this.vertauschung[i] = i; + } + + String[] tmp = v.split(" "); + + for (int i = 0; i < tmp.length; i++) { + if (tmp[i].length() != 2) continue; + + // lege bei beiden Buchstaben den vertauschten Index ab + int i1 = tmp[i].charAt(0) - 'A'; + int i2 = tmp[i].charAt(1) - 'A'; + + this.vertauschung[i1] = i2; + this.vertauschung[i2] = i1; + } + } + + /** + * Durchläuft das Steckbrett + * @param c Eingabebuchstabe + * @return Ausgabebuchstabe + */ + public char in(char c) { + int index = c - 'A'; + + return (char)(this.vertauschung[index] + 'A'); + } +} diff --git a/Verschlüsselung/src/Enigma/Walze.java b/Verschlüsselung/src/Enigma/Walze.java new file mode 100644 index 0000000..b20dbdf --- /dev/null +++ b/Verschlüsselung/src/Enigma/Walze.java @@ -0,0 +1,63 @@ +package Enigma; + +public class Walze { + + private String code; + private int[] verschiebungen; + + private int ring; + private int stellung; + + /** + * legt eine Walze an + * @param code auf welche Buchstaben das Alphabet abgebildet wird + * @param ring bei welcher Stellung die nächste Walze ausgelöst werden soll + * @param stellung Ausgangsstellung + */ + public Walze(String code, int ring, int stellung) { + this.code = code; + this.verschiebungen = new int[code.length()]; + for (int i = 0; i < code.length(); i++) { + this.verschiebungen[i] = code.charAt(i) - 'A' - i; + + // System.out.print(this.verschiebungen[i] + " , "); + } + // System.out.println(); + + this.ring = ring % 26; + this.stellung = stellung % 26; + } + + /** + * dreht die Walze eine Stellung weiter + * @return true, wenn nächste Walze gedreht werden soll + */ + public boolean next() { + stellung = (stellung + 1) % 26; + return stellung == ring; + } + + /** + * Vertauscht die Buchstaben in Eingangsrichtung + * @param c Eingangsbuchstabe + * @return Ausgangsbuchstabe + */ + public char in(char c) { + int index = c - 'A'; + int verschiebung = this.verschiebungen[(index + stellung) % 26]; + + return (char)((index + 26 + verschiebung) % 26 + 'A'); + } + + /** + * Vertauscht die Buchstaben in Rückrichtung + * @param c Eingangsbuchstabe + * @return Ausgangsbuchstabe + */ + public char out(char c) { + int index = this.code.indexOf((c - 'A' + stellung) % 26 + 'A'); + int verschiebung = -this.verschiebungen[(index) % 26]; + + return (char)((c - 'A' + 26 + verschiebung) % 26 + 'A'); + } +}