Част III. Програмният код
Настоящата статия е разделена в няколко публикации на блога: |
Част I. Принцип на работа на Енигма машина |
Част II. Детайли за роторите и математически модел на машината |
Част III. Програмният код |
Последна редакция: 26.02.2016г. |
След подробното излагане на принципите и особеностите на Енигма машините, сме готови да преминем към написването на програмния код. Започваме с няколко "сервизни" класове и интерфейси.
Alphabet е клас, който съдържа константата ALPHABET със стойност "ABCDEFG...". Ролята на ALPHABET е от нея да се изчитат позициите на буквите в азбуката, които се използват от Енигма роторите.
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; public final class Alphabet { /** * Constant string with all capital Latin letters of the alphabet in alphabetical * order. It's needed to establish the order of letters. A is 0, B is 1 etc. * and we get it by checking the position of each letter the string. */ public final static String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
Интерфейсът EnigmaComponent се реализира от класове, които емулират елемент на Енигма машината, внасящ пермутация в математическия ѝ модел.
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; public interface EnigmaComponent { public char permuteChar (char input); public char invertChar (char input); }
Имаме и специфично инстанцирано изключение.
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; public class InvalidEnigmaConfiguration extends IllegalArgumentException { public InvalidEnigmaConfiguration(String message) { super(message); } }
EnigmaPermutation инициализира пермутация на буквите от латинската азбука в нотация на Коши и предоставя методи за прилагането и върху букви от латинската азбука.
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; /** * Encapsulates the permutation functionality needed by Enigma. * <p> * Enigma machines permute the letters of Latin alphabet and are * case-insensitive. So this class facilitates working * with permutations of capital letters of the Latin alphabet. * * @author Angelin Lalev * */ public class EnigmaPermutation { protected String permutation; /** * No-argument constructor, which creates neutral permutation of the captial latin letters * (Each letter is sent to itself). */ public EnigmaPermutation() { permutation = Alphabet.ALPHABET; } /** * Creates user-specified permutation. * @param permutation gives the permutation in Cauchy notation. More specifically, * it gives the second line of the "table". In example the value for @param permutation of * "ZABCDEFGHIJKLMNOPQRSTUVWXY" sets the permutation so, that it sends * A to Z, B to A, C to B etc. */ public EnigmaPermutation(String permutation) { for (int i=0; i<Alphabet.ALPHABET.length(); i++) { if (!permutation.contains(Character.toString(Alphabet.ALPHABET.charAt(i)))) { throw new InvalidEnigmaConfiguration("Invalid Enigma permutation"); } } if (Alphabet.ALPHABET.length()!=permutation.length()) { throw new InvalidEnigmaConfiguration("Invalid Enigma permutation"); } this.permutation = permutation; } /** * Applies the permutation to a letter * * @param input contains the letter to be permuted * @return returns the resulting letter */ public char permute(char input) { return permutation.charAt(Alphabet.ALPHABET.indexOf(input)); } /** * Applies the <em>inverse</em> permutation to a letter * * @param input contains the letter to be permuted * @return returns the resulting letter */ public char invert(char input) { return Alphabet.ALPHABET.charAt(permutation.indexOf(input)); } }
EnigmaRhoPermutation описва пермутации, които отговарят на въртенето на ротора, както и на отместванията на азбучните пръстени на роторите. Тези пермутации всъщност са циклична група с генератор "BCDEF...YZA".
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; /** * Creates a member of the group of permutations that are needed to represent the movement of an * Enigma rotor. This group is cyclic. All of the permutations in the group are compositions of a basic * "generator" permutation with itself. The basic permutation sends A to B, * B to C, C to D etc. it can be "composed" several times with itself, giving any other member * of this group. * * @author Angelin Lalev * */ public class EnigmaRhoPermutation extends EnigmaPermutation { protected int times; /** * No-argument constructor that creates an instance that represents neutral permutation of the * capital Latin letters (Each letter is sent to itself). */ public EnigmaRhoPermutation() { super(); times=0; } /** * Creates an instance, representing the n-th member of the permutation group. */ public EnigmaRhoPermutation(int times) { super(); advance(times); } /** * Applies the basic permutation to the current one n times to get the n-th next permutation in the * group. The result becomes the new current permutation, which is represented by the instance. */ public void advance(int times) { String newperm = permutation; int tmptimes = times % permutation.length(); for (int i=0; i<tmptimes; i++) { newperm = permutation.substring(1, permutation.length()); permutation = newperm+permutation.substring(0,1); } this.times = (tmptimes+times)%permutation.length(); } }
Основният клас, който инкапсулира функционалността на Енигма машината, разглеждана като формула, е EnigmaMachine.
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; import java.util.ArrayList; /** * Class that encapsulates the functionality of the Enigma machine. * * @author Angelin Lalev * */ public class EnigmaMachine { public static final int MIN_ROTOR_COUNT = 3; protected ArrayList<EnigmaRotor> rotors; protected EnigmaReflector reflector; protected EnigmaSteckerBoard steckerboard; protected EnigmaETW etw; protected boolean valid; /** * Constructs classical EnigmaMachine * @param rotor1 - The rightmost rotor * @param rotor2 - The middle rotor * @param rotor3 - The leftmost rotor * @param rotor4 - Eventually, a forth rotor, to the left of the current leftmost rotor * @param reflector - The reflector of the machine * @param steckerboard - The steckerboard of the machine * @param etw - The ETW ring of the machine */ public EnigmaMachine(EnigmaRotor rotor1, EnigmaRotor rotor2, EnigmaRotor rotor3, EnigmaRotor rotor4, EnigmaReflector reflector, EnigmaSteckerBoard steckerboard, EnigmaETW etw) { if ((rotor1 == null) || (rotor2==null) || (rotor3==null)) { throw new InvalidEnigmaConfiguration("At least rotors 1, 2 and 3 must be intialized"); } if (reflector==null) { throw new InvalidEnigmaConfiguration("Reflector of the Enigma machine must be initialized."); } if (steckerboard==null) { this.steckerboard = new EnigmaSteckerBoard(); } if (etw == null) { this.etw = new EnigmaETW(); } rotors = new ArrayList<EnigmaRotor>(MIN_ROTOR_COUNT); this.rotors.add(rotor1); this.rotors.add(rotor2); this.rotors.add(rotor3); if (rotor4!=null) { this.rotors.add(rotor4); } this.reflector = reflector; this.steckerboard = steckerboard; this.valid = true; } public EnigmaMachine() { rotors = new ArrayList<EnigmaRotor>(MIN_ROTOR_COUNT); this.valid = false; } public void addRotor(EnigmaRotor rotor) { if (rotor!=null) { rotors.add(rotor); } } public void addReflector(EnigmaReflector reflector) { if (reflector!=null) { this.reflector = reflector; } } public void addSteckerBoard(EnigmaSteckerBoard steckerboard) { if (steckerboard!=null) { this.steckerboard = steckerboard; } } public void addETW(EnigmaETW etw) { if (etw!=null) { this.etw = etw; } } public void validate() { for (int i=0; i<MIN_ROTOR_COUNT; i++) { try { if (rotors.get(i)==null) { throw new InvalidEnigmaConfiguration("At least "+ MIN_ROTOR_COUNT + "rotors must be present in an Enigma machine"); } } catch (IndexOutOfBoundsException e) { throw new InvalidEnigmaConfiguration("At least " + MIN_ROTOR_COUNT + "rotors must be present in an Enigma machine"); } } if (reflector==null) { throw new InvalidEnigmaConfiguration("No reflector added to machine"); } if (steckerboard==null) { throw new InvalidEnigmaConfiguration("No steckerboard added to machine"); } if (etw==null) { throw new InvalidEnigmaConfiguration("No etw added to machine"); } valid = true; } /** * Moves the rotors according to notches and takes into account * the double step phenomena. * */ public void stepRotors() { if (!valid) { throw new InvalidEnigmaConfiguration("Enigma configuration must be validated before being used!"); } rotors.get(0).markForMovement(); for (int i=1; i<rotors.size(); i++) { if (rotors.get(i-1).onNotch()) { rotors.get(i).markForMovement(); rotors.get(i-1).markForMovement(); } } for (int i=0; i<rotors.size(); i++) { rotors.get(i).move(); } } /** * Returns a string that represent the current rotor poisitions * of each rotor. The leftmost char is the leftmost rotor. * * @return */ public String getRotorPositions() { String result=""; for (int i=rotors.size()-1; i>=0; i--) { result=result+rotors.get(i).getPositionChar(); } return result; } public char encodeChar(char input) { char output; if (!valid) { throw new InvalidEnigmaConfiguration("Enigma configuration must be validated before being used!"); } stepRotors(); output = steckerboard.permuteChar(input); output = etw.permuteChar(output); for (int i=0; i<rotors.size(); i++) { output = rotors.get(i).permuteChar(output); } output = reflector.permuteChar(output); for (int i=rotors.size()-1; i>=0; i--) { output = rotors.get(i).invertChar(output); } output = etw.invertChar(output); output = steckerboard.invertChar(output); return output; } public String encodeMessage(String message) { String result=""; for (int i=0; i<message.length(); i++) { result = result+encodeChar(message.charAt(i)); } return result; } }
EnigmaMachine притежава списък с ротори, които са реализирани като инстанции на EnigmaRotor.
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; /** * Emulates an Engima rotor. * <p> * It does so by creating a EnigmaPermutation that corresponds to * the rotor wirings. Additionally, it creates two EnigmaRhoPermutations * that correspond respectively to ring offset and rotor position. * One that has the rotor position can "advance" to simulate the rotor * movement. * * @author Angelin Lalev * */ public class EnigmaRotor implements EnigmaComponent { public static final String[][] ROTOR_CONFIGURATIONS = {{"I","EKMFLGDQVZNTOWYHXUSPAIBRCJ", "Q"}, {"II", "AJDKSIRUXBLHWTMCQGZNPYFVOE", "E"}, {"III", "BDFHJLCPRTXVZNYEIWGAKMUSQO", "V"}, {"IV", "ESOVPZJAYQUIRHXLNFTGKDCMWB", "J"}, {"V", "VZBRGITYUPSDNHLXAWMJQOFECK", "Z"}, {"VI", "JPGVOUMFYQBENHZRDKASXLICTW", "ZM"}, {"VII", "NZJHGRCXMYSWBOUFAIVLPEKQDT", "ZM"}, {"VIII", "FKQHTLXOCBJSPDZRAMEWNIUYGV", "ZM"}, }; // private String type; private String notches; private EnigmaRhoPermutation positionPerm; private EnigmaRhoPermutation ringPerm; private EnigmaPermutation rotorPerm; private char positionChar; // private char ringChar; private boolean markedForMovement; public char permuteChar(char input) { return positionPerm.invert( ringPerm.permute( rotorPerm.permute( ringPerm.invert( positionPerm.permute(input) )))); } public char invertChar(char input) { return positionPerm.invert( ringPerm.permute( rotorPerm.invert( ringPerm.invert( positionPerm.permute(input) )))); } public void makeStep() { positionPerm.advance(1); if (positionChar=='Z') { positionChar='A'; } else { positionChar++; } } public void markForMovement() { markedForMovement = true; } public void move() { if (markedForMovement) { makeStep(); }; markedForMovement = false; } public boolean onNotch() { return notches.contains(Character.toString(positionChar)); } /** * Returns current position on the alphabetic ring of the rotor. */ public char getPositionChar() { return positionChar; } /** * Create EnigmaRotor with historically correct configuration * * @param rotorType - the type of the rotor. Military Enigma machines had eight standard rotor configurations. * @param ringOffset - the offset of the alphabet ring * @param rotorPosition - the initial position of the rotor */ public EnigmaRotor(String rotorType, char ringOffset, char rotorPosition) { // this.ringChar = ringOffset; this.positionChar = rotorPosition; this.ringPerm = new EnigmaRhoPermutation(Alphabet.ALPHABET.indexOf(ringOffset)); this.positionPerm = new EnigmaRhoPermutation(Alphabet.ALPHABET.indexOf(rotorPosition)); this.markedForMovement = false; for (int c=0; c<ROTOR_CONFIGURATIONS.length; c++) { if (ROTOR_CONFIGURATIONS[c][0].equals(rotorType)) { // this.type=ROTOR_CONFIGURATIONS[c][0]; this.rotorPerm = new EnigmaPermutation(ROTOR_CONFIGURATIONS[c][1]); this.notches=ROTOR_CONFIGURATIONS[c][2]; return; } } throw new InvalidEnigmaConfiguration("Rotor "+rotorType+" is not in the list of known rotors."); } /** * Construct custom Enigma rotor * @param permutation - gives the permutation of the alphabet that this rotor facilitates. * @param rotorType - readable user-specified description of the rotor. * @param ringOffset - offset of the alphabet ring of the rotor * @param rotorPosition - the initial position of the rotor * @param notches - a String that describes all the notches of the ring with the corresponding letter names on the ring. */ public EnigmaRotor(String permutation, String rotorType, char ringOffset, char rotorPosition, String notches) { this.ringPerm = new EnigmaRhoPermutation(Alphabet.ALPHABET.indexOf(ringOffset)); this.positionPerm = new EnigmaRhoPermutation(Alphabet.ALPHABET.indexOf(rotorPosition)); this.markedForMovement = false; //this.type = rotorType; this.rotorPerm = new EnigmaPermutation(permutation); this.notches = notches; } }
... и един рефлектор, който е реализиран от класа EnigmaReflector.
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; public class EnigmaReflector implements EnigmaComponent { public static final String[][] REFLECTOR_CONFIGURATIONS = {{"A","EJMZALYXVBWFCRQUONTSPIKHGD"}, {"B", "YRUHQSLDPXNGOKMIEBFZCWVJAT"}, {"C", "FVPJIAOYEDRZXWGCTKUQSBNMHL"}, {"B Thin", "ENKQAUYWJICOPBLMDXZVFTHRGS"}, {"C Thin", "RDOBJNTKVEHMLFCWZAXGYIPSUQ"}, }; // private String type; protected EnigmaPermutation reflectorPerm; /** * Creates a historically accurate Enigma reflector * * @param reflectorType */ public EnigmaReflector(String reflectorType) { for (int c=0; c<REFLECTOR_CONFIGURATIONS.length; c++) { if (reflectorType.equals(REFLECTOR_CONFIGURATIONS[c][0])) { // type=REFLECTOR_CONFIGURATIONS[c][0]; reflectorPerm = new EnigmaPermutation(REFLECTOR_CONFIGURATIONS[c][1]); return; } } throw new InvalidEnigmaConfiguration("Reflector "+reflectorType+" is not in the list of known reflectors."); } public EnigmaReflector(String permutation, String reflectorType) { reflectorPerm = new EnigmaPermutation(permutation); for (int i=0; i<permutation.length(); i++) { if (reflectorPerm.permute(reflectorPerm.permute(Alphabet.ALPHABET.charAt(i)))!=Alphabet.ALPHABET.charAt(i)) { throw new InvalidEnigmaConfiguration("Reflector permutation must be inverse to itself."); } } } public char permuteChar(char input) { return reflectorPerm.permute(input); } public char invertChar(char input) { return reflectorPerm.invert(input); } };
EnigmaSteckerBoard реализира щекерно табло.
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; public class EnigmaSteckerBoard implements EnigmaComponent { protected EnigmaPermutation steckerPerm; public EnigmaSteckerBoard(String permutation) { this.steckerPerm = new EnigmaPermutation(permutation); } public EnigmaSteckerBoard() { this.steckerPerm = new EnigmaPermutation(Alphabet.ALPHABET); } public char permuteChar(char input) { return steckerPerm.permute(input); } public char invertChar(char input) { return steckerPerm.invert(input); } }
А EnigmaETW реализира пермутацията на входното колело.
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.enigmasim; public class EnigmaETW implements EnigmaComponent { protected EnigmaPermutation etwPerm; /** * Creates custom ETW * @param permutation - String that describe */ public EnigmaETW (String permutation) { this.etwPerm = new EnigmaPermutation(permutation); } /** * Constructs an ETW that does not permute anything. Such ETW is typical * for military Enigmas. */ public EnigmaETW () { this.etwPerm = new EnigmaPermutation(Alphabet.ALPHABET); } public char permuteChar(char input) { return etwPerm.permute(input); } public char invertChar(char input) { return etwPerm.invert(input); } }
/* * This file is authored by Angelin Lalev and may be * distributed under GPLv3 license which may be * obtained from: * http://www.gnu.org/licenses/gpl-3.0.en.html */ package code.lalev.engimasim.unittests; import code.lalev.enigmasim.*; public class EnigmaTest { public static void main(String[] args) { System.out.println("Unit tests for code.lalev.enigmasim package"); System.out.println("==========================================="); System.out.print("Constructing I,II,III,B Enigma with no steckerboard or etw ... "); EnigmaMachine enigma = new EnigmaMachine(); EnigmaRotor rotor = new EnigmaRotor("I",'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("II", 'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("III", 'A', 'A'); enigma.addRotor(rotor); EnigmaReflector reflector = new EnigmaReflector("B"); enigma.addReflector(reflector); EnigmaETW etw = new EnigmaETW(); enigma.addETW(etw); EnigmaSteckerBoard board = new EnigmaSteckerBoard(); enigma.addSteckerBoard(board); enigma.validate(); System.out.println("SUCCESS"); System.out.print("Constructing IV,V,VI,VII,VII,C Enigma with (AB)(CD)(EF)(GH) steckerboard and no etw ... "); enigma = new EnigmaMachine(); rotor = new EnigmaRotor("IV",'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("V", 'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("VI", 'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("VII", 'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("VIII", 'A', 'A'); enigma.addRotor(rotor); reflector = new EnigmaReflector("C"); enigma.addReflector(reflector); etw = new EnigmaETW(); enigma.addETW(etw); board = new EnigmaSteckerBoard("BADCFEHGIJKLMNOPQRSTUVWXYZ"); enigma.addSteckerBoard(board); enigma.validate(); System.out.println("SUCCESS"); System.out.print("Catching invalid Enigma with 2 rotors... "); enigma = new EnigmaMachine(); rotor = new EnigmaRotor("IV",'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("V", 'A', 'A'); enigma.addRotor(rotor); reflector = new EnigmaReflector("C"); enigma.addReflector(reflector); etw = new EnigmaETW(); enigma.addETW(etw); board = new EnigmaSteckerBoard("BADCFEHGIJKLMNOPQRSTUVWXYZ"); enigma.addSteckerBoard(board); try { enigma.validate(); System.out.println("FAIL"); } catch (Exception e) { System.out.println("SUCCESS"); } System.out.println("Rotor movement and double stepping tests ...IN PROGRESS"); enigma = new EnigmaMachine(); rotor = new EnigmaRotor("I",'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("II", 'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("III", 'A', 'A'); enigma.addRotor(rotor); reflector = new EnigmaReflector("C"); enigma.addReflector(reflector); etw = new EnigmaETW(); enigma.addETW(etw); board = new EnigmaSteckerBoard(); enigma.addSteckerBoard(board); enigma.validate(); System.out.println("Test 1"); String desiredoutput = "AAA AAB AAC AAD AAE AAF AAG AAH AAI AAJ "; String realoutput=""; System.out.println("Correct: "+desiredoutput); for (int i=0; i<10; i++) { realoutput=realoutput+enigma.getRotorPositions()+" "; enigma.stepRotors(); } System.out.println("Result: "+realoutput); if (desiredoutput.equals(realoutput)) { System.out.println("SUCCESS"); } else { System.out.println("FAILURE"); } enigma = new EnigmaMachine(); rotor = new EnigmaRotor("I",'A', 'O'); enigma.addRotor(rotor); rotor = new EnigmaRotor("II", 'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("III", 'A', 'A'); enigma.addRotor(rotor); reflector = new EnigmaReflector("C"); enigma.addReflector(reflector); etw = new EnigmaETW(); enigma.addETW(etw); board = new EnigmaSteckerBoard(); enigma.addSteckerBoard(board); enigma.validate(); System.out.println("Test 2"); desiredoutput = "AAO AAP AAQ ABR ABS ABT "; realoutput=""; System.out.println("Correct: "+desiredoutput); for (int i=0; i<6; i++) { realoutput=realoutput+enigma.getRotorPositions()+" "; enigma.stepRotors(); } System.out.println("Result: "+realoutput); if (desiredoutput.equals(realoutput)) { System.out.println("SUCCESS"); } else { System.out.println("FAILURE"); } enigma = new EnigmaMachine(); rotor = new EnigmaRotor("III",'Z', 'U'); enigma.addRotor(rotor); rotor = new EnigmaRotor("II", 'P', 'D'); enigma.addRotor(rotor); rotor = new EnigmaRotor("I", 'Q', 'A'); enigma.addRotor(rotor); reflector = new EnigmaReflector("C"); enigma.addReflector(reflector); etw = new EnigmaETW(); enigma.addETW(etw); board = new EnigmaSteckerBoard(); enigma.addSteckerBoard(board); enigma.validate(); System.out.println("Test 3 (Double step)"); desiredoutput = "ADU ADV AEW BFX BFY "; realoutput=""; System.out.println("Correct: "+desiredoutput); for (int i=0; i<5; i++) { realoutput=realoutput+enigma.getRotorPositions()+" "; enigma.stepRotors(); } System.out.println("Result: "+realoutput); if (desiredoutput.equals(realoutput)) { System.out.println("SUCCESS"); } else { System.out.println("FAILURE"); } System.out.println("Testing encryption ... IN PROGRESS"); System.out.println("Test 1. Encrypt: Rotors I, II, III, GrundStellung:AAA Ringstellung:AAA, Refl. B, no etw, Steckerboard:(AB)(CD)"); enigma = new EnigmaMachine(); rotor = new EnigmaRotor("I",'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("II", 'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("III", 'A', 'A'); enigma.addRotor(rotor); reflector = new EnigmaReflector("B"); enigma.addReflector(reflector); etw = new EnigmaETW(); enigma.addETW(etw); board = new EnigmaSteckerBoard("BADCEFGHIJKLMNOPQRSTUVWXYZ"); enigma.addSteckerBoard(board); enigma.validate(); String plaintext = "AAAAAAAA"; String ciphertext = "WUPGNWOJ"; String result = enigma.encodeMessage(plaintext); System.out.println("Plaintext:"+plaintext); System.out.println("Ciphertext:"+ciphertext); System.out.println("Result:"+result); if (result.equals(ciphertext)) { System.out.println("SUCCESS"); } else { System.out.println("FAILURE"); } System.out.println("Test 2. Decrypt: Rotors I, II, III, GrundStellung:AAA Ringstellung:AAA, Refl. B, no etw, Steckerboard:(AB)(CD)"); enigma = new EnigmaMachine(); rotor = new EnigmaRotor("I",'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("II", 'A', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("III", 'A', 'A'); enigma.addRotor(rotor); reflector = new EnigmaReflector("B"); enigma.addReflector(reflector); etw = new EnigmaETW(); enigma.addETW(etw); board = new EnigmaSteckerBoard("BADCEFGHIJKLMNOPQRSTUVWXYZ"); enigma.addSteckerBoard(board); enigma.validate(); plaintext = "AAAAAAAA"; ciphertext = "WUPGNWOJ"; result = enigma.encodeMessage(ciphertext); System.out.println("Plaintext:"+plaintext); System.out.println("Ciphertext:"+ciphertext); System.out.println("Result:"+result); if (result.equals(plaintext)) { System.out.println("SUCCESS"); } else { System.out.println("FAILURE"); } System.out.println("Test 3. Encrypt: Rotors IV, V, VI, GrundStellung:AAA Ringstellung:BBB, Refl.C, no etw, Steckerboard:(AB)(CD)"); enigma = new EnigmaMachine(); rotor = new EnigmaRotor("VI",'B', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("V", 'B', 'A'); enigma.addRotor(rotor); rotor = new EnigmaRotor("IV", 'B', 'A'); enigma.addRotor(rotor); reflector = new EnigmaReflector("C"); enigma.addReflector(reflector); etw = new EnigmaETW(); enigma.addETW(etw); board = new EnigmaSteckerBoard("BADCEFGHIJKLMNOPQRSTUVWXYZ"); enigma.addSteckerBoard(board); enigma.validate(); plaintext = "AAAAAAAA"; ciphertext = "TDKWFFQE"; result = enigma.encodeMessage(plaintext); System.out.println("Plaintext:"+plaintext); System.out.println("Ciphertext:"+ciphertext); System.out.println("Result:"+result); if (result.equals(ciphertext)) { System.out.println("SUCCESS"); } else { System.out.println("FAILURE"); } } }