Enigma hinzugefügt

master
akimmig 2022-02-16 18:23:45 +01:00
parent 41eeed22bb
commit 56582e5399
4 changed files with 257 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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');
}
}

View File

@ -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');
}
}