init
This commit is contained in:
BIN
Enigma/Enigma.class
Normal file
BIN
Enigma/Enigma.class
Normal file
Binary file not shown.
67
Enigma/Enigma.java
Normal file
67
Enigma/Enigma.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Enigma Class with method for en-/decoding of characters.
|
||||
* Constructs the Enigma.
|
||||
*/
|
||||
public class Enigma {
|
||||
|
||||
/**
|
||||
* Patchboard of the Enigma.
|
||||
*/
|
||||
private PatchBoard patchboard;
|
||||
|
||||
/**
|
||||
* Reflector of the Engima.
|
||||
*/
|
||||
private Reflector reflector;
|
||||
|
||||
/**
|
||||
* Array of variable mount of Enigma's rotors.
|
||||
*/
|
||||
private Rotor[] rotor;
|
||||
|
||||
/**
|
||||
* Creates the Enigma with patchboard, reflector and all the rotors.
|
||||
* Arguments are committed by the Shell.
|
||||
* @param tickPos tick-position-array for all rotors
|
||||
* @param initialPos initial-position-array
|
||||
* @param permu permutation-array-array
|
||||
* @param patchboardpermu Permutation for the patchboard
|
||||
* @param reflectorpermu Permutation for the reflector
|
||||
*/
|
||||
Enigma(final int[] tickPos, final int[] initialPos, final int[][] permu
|
||||
, final int[] patchboardpermu, final int[] reflectorpermu) {
|
||||
this.patchboard = new PatchBoard(patchboardpermu);
|
||||
this.reflector = new Reflector(reflectorpermu);
|
||||
rotor = new Rotor[tickPos.length];
|
||||
for (int i = 0; i < tickPos.length; i++) {
|
||||
rotor[i] = new Rotor(tickPos[i],
|
||||
initialPos[i], permu[i]);
|
||||
if (0 < i) {
|
||||
this.rotor[i - 1].setNext(rotor[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for en-/decoding of a Character. Calls one by one the patchboard
|
||||
* , all the rotors, the Reflector, back again all the rotors and finally
|
||||
* again the patchboard like in the Enigma, used by the Germans in WW2.
|
||||
* @param symbol int-value of a Character
|
||||
* @return en-/decoded value of a Character
|
||||
*/
|
||||
public final int encode(final int symbol) {
|
||||
int i = symbol;
|
||||
i = patchboard.encode(i);
|
||||
for (int j = 0; j < rotor.length; j++) {
|
||||
i = rotor[j].encode(i);
|
||||
}
|
||||
i = reflector.encode(i);
|
||||
for (int k = rotor.length - 1; k >= 0; k--) {
|
||||
i = this.rotor[k].decode(i);
|
||||
}
|
||||
i = patchboard.decode(i);
|
||||
rotor[0].tick();
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
BIN
Enigma/EnigmaComponent.class
Normal file
BIN
Enigma/EnigmaComponent.class
Normal file
Binary file not shown.
33
Enigma/EnigmaComponent.java
Normal file
33
Enigma/EnigmaComponent.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Interface EnigmaComponent unifies rotors, patchboard and reflector
|
||||
* of an enigma.
|
||||
*/
|
||||
interface EnigmaComponent {
|
||||
|
||||
/**
|
||||
* Applies the substitution chiffre of this enigma component in the current
|
||||
* state to symbol.
|
||||
*
|
||||
* @param symbol The symbol to encode with the substitution chiffre of this
|
||||
* enigma component in its current state.
|
||||
* @return The symbol which is the encoded symbol of the parameter symbol.
|
||||
*/
|
||||
int encode(int symbol);
|
||||
|
||||
/**
|
||||
* Applies the inverse substitution chiffre of this enigma component in the
|
||||
* current state to letter.
|
||||
*
|
||||
* @param symbol The symbol to decode with the (inverse) substitution
|
||||
* chiffre of this enigma component in its current state.
|
||||
* @return The symbol which is the decoded symbol of the parameter symbol.
|
||||
*/
|
||||
int decode(int symbol);
|
||||
|
||||
/**
|
||||
* In case this component can do ticks, this component performs its next
|
||||
* tick. In case this triggers ticks of subsequent components, their ticks
|
||||
* are also triggered.
|
||||
*/
|
||||
void tick();
|
||||
}
|
||||
BIN
Enigma/PatchBoard.class
Normal file
BIN
Enigma/PatchBoard.class
Normal file
Binary file not shown.
59
Enigma/PatchBoard.java
Normal file
59
Enigma/PatchBoard.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Patchboard for a Enigma.
|
||||
*/
|
||||
public class PatchBoard implements EnigmaComponent {
|
||||
/**
|
||||
* Permutation for the patchboard.
|
||||
*/
|
||||
private int[] permu;
|
||||
|
||||
/**
|
||||
* Inverse permutation for the patchboard.
|
||||
*/
|
||||
private int[] invPermu;
|
||||
|
||||
/**
|
||||
* Constructor for the patchboard.
|
||||
* @param permu permutation
|
||||
*/
|
||||
PatchBoard(final int[] permu) {
|
||||
this.permu = permu;
|
||||
this.invPermu = calcInvPermu(permu);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final int encode(final int i) {
|
||||
return permu[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final int decode(final int i) {
|
||||
return invPermu[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final void tick() {
|
||||
}
|
||||
/**
|
||||
* Calculates the inverese permutation.
|
||||
* @param permu permutation
|
||||
* @return <code>inverse permutation</code>
|
||||
*/
|
||||
private int[] calcInvPermu(final int[] permu) {
|
||||
int[] array = new int[permu.length];
|
||||
for (int i = 0; i < permu.length; i++) {
|
||||
for (int k = 0; k < permu.length; k++) {
|
||||
if (i == permu[k]) {
|
||||
array[i] = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
BIN
Enigma/Reflector.class
Normal file
BIN
Enigma/Reflector.class
Normal file
Binary file not shown.
40
Enigma/Reflector.java
Normal file
40
Enigma/Reflector.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Reflector for the Enigma.
|
||||
*
|
||||
*/
|
||||
public class Reflector implements EnigmaComponent {
|
||||
|
||||
/**
|
||||
* Permutation of the reflector.
|
||||
*/
|
||||
private int[] permu;
|
||||
/**
|
||||
* Permutation of reflector.
|
||||
* @param permu Permutation
|
||||
*/
|
||||
Reflector(final int[] permu) {
|
||||
this.permu = permu;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final int encode(final int i) {
|
||||
return permu[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is not required in the reflector.<br />
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final int decode(final int i) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void tick() {
|
||||
|
||||
}
|
||||
}
|
||||
BIN
Enigma/Rotor.class
Normal file
BIN
Enigma/Rotor.class
Normal file
Binary file not shown.
109
Enigma/Rotor.java
Normal file
109
Enigma/Rotor.java
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Class for the rotors of the Enigma.
|
||||
*
|
||||
*/
|
||||
public class Rotor implements EnigmaComponent {
|
||||
/**
|
||||
* Position where rotor "ticks" next rotor.
|
||||
*/
|
||||
private int tickPos;
|
||||
|
||||
/**
|
||||
* Current position of the rotor.
|
||||
*/
|
||||
private int initialPos;
|
||||
|
||||
/**
|
||||
* If Rotor has succesor.
|
||||
*/
|
||||
private Rotor next;
|
||||
|
||||
/**
|
||||
* Permutation of the rotor.
|
||||
*/
|
||||
private int[] permu;
|
||||
|
||||
/**
|
||||
* Inverse permutation of the rotor.
|
||||
*/
|
||||
private int[] invPermu;
|
||||
|
||||
/**
|
||||
* @param tickPos Position where rotor "ticks" next rotor
|
||||
* @param initialPos Current position of the rotor
|
||||
* @param permu Permutation of the rotor
|
||||
*/
|
||||
Rotor(final int tickPos, final int initialPos, final int[] permu) {
|
||||
this.tickPos = tickPos;
|
||||
this.initialPos = initialPos;
|
||||
this.permu = permu;
|
||||
this.invPermu = calcInvPermu(permu);
|
||||
this.next = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the next-rotor-pointer.
|
||||
* @param next Next rotor
|
||||
*/
|
||||
public final void setNext(final Rotor next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the inverese permutation.
|
||||
* @param permu permutation
|
||||
* @return <code>inverse permutation</code>
|
||||
*/
|
||||
private int[] calcInvPermu(final int[] permu) {
|
||||
int[] array = new int[permu.length];
|
||||
for (int i = 0; i < permu.length; i++) {
|
||||
for (int k = 0; k < permu.length; k++) {
|
||||
if (i == permu[k]) {
|
||||
array[i] = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final int encode(final int i) {
|
||||
if (((permu[((initialPos + i) % permu.length)] - initialPos
|
||||
+ permu.length) % permu.length) < 0) {
|
||||
return (((permu[((initialPos + i) % permu.length)]
|
||||
- initialPos + permu.length)
|
||||
% permu.length) + permu.length);
|
||||
}
|
||||
return (permu[((initialPos + i) % permu.length)]
|
||||
- initialPos + permu.length) % permu.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final int decode(final int i) {
|
||||
if (((invPermu[((initialPos + i) % permu.length)]
|
||||
- initialPos + permu.length) % permu.length) < 0) {
|
||||
return (((invPermu[((initialPos + i) % permu.length)]
|
||||
- initialPos + permu.length)
|
||||
% permu.length) + permu.length);
|
||||
}
|
||||
return (invPermu[((initialPos + i) % permu.length)]
|
||||
- initialPos + permu.length) % permu.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final void tick() {
|
||||
if (initialPos == permu.length) {
|
||||
initialPos = 0;
|
||||
}
|
||||
initialPos++;
|
||||
if (initialPos == (tickPos + 1) && next != null) {
|
||||
next.tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Enigma/Shell.class
Normal file
BIN
Enigma/Shell.class
Normal file
Binary file not shown.
252
Enigma/Shell.java
Normal file
252
Enigma/Shell.java
Normal file
@@ -0,0 +1,252 @@
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Main Class for interaction with the user.
|
||||
*
|
||||
*/
|
||||
public final class Shell {
|
||||
/**
|
||||
* number of arguments / rotor.
|
||||
*/
|
||||
private static final int ROTORARGS = 3;
|
||||
/**
|
||||
* Patchboard-permutation.
|
||||
*/
|
||||
private static final int[] PATCHBOARDPERMU = new int[] {9, 22, 20, 11, 2, 12
|
||||
, 13, 14, 7, 15, 16, 25, 24, 23, 8, 17, 0, 3, 10, 4, 6, 21, 1, 19
|
||||
, 18, 5};
|
||||
|
||||
/**
|
||||
* Reflector- permutation.
|
||||
*/
|
||||
private static final int[] REFLECTORPERMU = new int[] {8, 12, 4, 19, 2, 6, 5
|
||||
, 17, 0, 24, 18, 16, 1, 25, 23, 22, 11, 7, 10, 3, 21, 20, 15, 14
|
||||
, 9, 13};
|
||||
|
||||
/**
|
||||
* Amount of Symbols the alphabet uses.
|
||||
*/
|
||||
private static int symbols = PATCHBOARDPERMU.length;
|
||||
|
||||
private Shell() { }
|
||||
|
||||
/**
|
||||
* Convert char-Array to Enigma-permutation-array.
|
||||
* @param charArray char-array to convert
|
||||
* @return Enigma-compatible <code>permutation array</code>
|
||||
*/
|
||||
private static int[] convertCharInt(final char[] charArray) {
|
||||
int[] intArray = new int[charArray.length];
|
||||
for (int i = 0; i < charArray.length; i++) {
|
||||
intArray[i] = (charArray[i] - 65);
|
||||
}
|
||||
return intArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Enigma-int to char.
|
||||
* @param i Enigma-int
|
||||
* @return <code>char</code>
|
||||
*/
|
||||
private static char convertIntChar(final int i) {
|
||||
return (char) (i + 65);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if every Parameter for a Enigma exists.
|
||||
* @param stringArray Array of all programm parameters
|
||||
* @return <code>true</code> if right number of parameters are given<br />
|
||||
* <code>false</code> if wrong number of parameters or parameters
|
||||
* are zero
|
||||
*/
|
||||
private static boolean checkArgsLength(final String[] stringArray) {
|
||||
return stringArray.length % ROTORARGS == 0 && stringArray.length != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the Permutation-Array Elements out of the Arguments
|
||||
* given by the User. <br /> Every third Element is a Permutation-Array.
|
||||
* Furthermore, the lengths of the Array is checked to handle faults.
|
||||
* @param stringAr the <code>String</code> entered by the user.
|
||||
* @return <code>Permutation-Array[][]</code> for every Rotor as a
|
||||
* char-array or<br /><code>null</code> if any error occurs.
|
||||
*/
|
||||
private static int[][] extractPermuArray(final String[] stringAr) {
|
||||
int[][] intArray = new int[(stringAr.length / ROTORARGS)]
|
||||
[Shell.symbols];
|
||||
for (int i = 0; i < (stringAr.length) / ROTORARGS; i++) {
|
||||
if (stringAr[(i * ROTORARGS)].length() == Shell.symbols) {
|
||||
intArray[i] = convertCharInt(
|
||||
stringAr[(i * ROTORARGS)].toCharArray());
|
||||
} else { return null; }
|
||||
}
|
||||
return intArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the tick-Positions out of string-array into a int-array.
|
||||
* @param stringAr All Arguments committed to the Programm
|
||||
* @return <code>int-array</code> with rotors tick-positions <br />
|
||||
* or <code>null</code> if tick-positition has more then
|
||||
* one character
|
||||
*/
|
||||
private static int[] extractTickPosArray(final String[] stringAr) {
|
||||
int[] intArray = new int[(stringAr.length / ROTORARGS)];
|
||||
for (int i = 0; i < (stringAr.length / ROTORARGS); i++) {
|
||||
if (stringAr[1 + (i * ROTORARGS)].toCharArray().length == 1) {
|
||||
intArray[i] = stringAr[1 + (i * ROTORARGS)].charAt(0) - 65;
|
||||
} else { return null; }
|
||||
}
|
||||
return intArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the initial-Positions out of string-array into a int-array.
|
||||
* @param stringAr All Arguments committed to the Programm
|
||||
* @return <code>int-array</code> with rotors initial-positions <br />
|
||||
* or <code>null</code> if initial-positition has more then
|
||||
* one character
|
||||
*/
|
||||
private static int[] extractInitialPosArray(final String[] stringAr) {
|
||||
int[] intArray = new int[(stringAr.length / ROTORARGS)];
|
||||
for (int i = 0; i < (stringAr.length / ROTORARGS); i++) {
|
||||
if (stringAr[2 + (i * ROTORARGS)].toCharArray().length == 1) {
|
||||
intArray[i] = stringAr[2 + (i * ROTORARGS)].charAt(0) - 65;
|
||||
} else { return null; }
|
||||
}
|
||||
return intArray;
|
||||
}
|
||||
/**
|
||||
* Checks if char is a capital-Letter.
|
||||
* @param ch Character
|
||||
* @return <code>true</code> <br >/
|
||||
* or <code>false</code>
|
||||
*/
|
||||
private static boolean isEnigmaChar(final int ch) {
|
||||
if (ch < 0 || ch >= Shell.symbols) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if char-array is a capital-Letter-array.
|
||||
* @param ch Character-array
|
||||
* @return <code>true</code> <br >/
|
||||
* or <code>false</code>
|
||||
*/
|
||||
private static boolean isEnigmaCharArray(final int[] ch) {
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
if (!isEnigmaChar(ch[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if char-array-array is a capital-Letter-array-array.
|
||||
* @param ch Character-array-array
|
||||
* @return <code>true</code> <br >/
|
||||
* or <code>false</code>
|
||||
*/
|
||||
private static boolean isEnigmaCharArray(final int[][] ch) {
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
if (!isEnigmaCharArray(ch[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Checks if a permutation contains a char twice.
|
||||
* @param permu Permutation
|
||||
* @return <code>true</code> if duplicate char is found<br />
|
||||
* <code>false</code> if chars are unique
|
||||
*/
|
||||
private static boolean hasDuplicateChar(final int[][] permu) {
|
||||
boolean[][] foo = new boolean[permu.length][permu[0].length];
|
||||
int i;
|
||||
int j;
|
||||
for (i = 0; i < permu.length; i++) {
|
||||
for (j = 0; j < permu[i].length; j++) {
|
||||
if (foo[i][permu[i][j]]) {
|
||||
return true;
|
||||
} else {
|
||||
foo[i][permu[i][j]] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method for the Enigma-Simulation.
|
||||
* @param args All parameter given to the Shell
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static void main(final String[] args) throws IOException {
|
||||
int[][] permu = new int[(args.length / ROTORARGS)][Shell.symbols];
|
||||
int[] tickPos = new int[(args.length / ROTORARGS)];
|
||||
int[] initialPos = new int[(args.length / ROTORARGS)];
|
||||
Enigma myEnigma;
|
||||
|
||||
if (checkArgsLength(args)) {
|
||||
if (extractPermuArray(args) != null) {
|
||||
permu = extractPermuArray(args);
|
||||
} else {
|
||||
System.out.println("Error! Wrong Permutation!");
|
||||
return;
|
||||
}
|
||||
if (extractTickPosArray(args) != null) {
|
||||
tickPos = extractTickPosArray(args);
|
||||
} else {
|
||||
System.out.println("Error! wrong Tick Position!");
|
||||
return;
|
||||
}
|
||||
if (extractInitialPosArray(args) != null) {
|
||||
initialPos = extractInitialPosArray(args);
|
||||
} else {
|
||||
System.out.println("Error! wrong initial Position!");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
System.out.println("Error: wrong number of Arguments");
|
||||
return;
|
||||
}
|
||||
//Check if only Capital Letters are used
|
||||
if (!isEnigmaCharArray(permu) || !isEnigmaCharArray(tickPos)
|
||||
|| !isEnigmaCharArray(initialPos)) {
|
||||
System.out.print("Error! wrong character in config");
|
||||
return;
|
||||
}
|
||||
if (hasDuplicateChar(extractPermuArray(args))) {
|
||||
System.out.println("Error! Duplicate char in Permutation");
|
||||
}
|
||||
|
||||
BufferedReader br =
|
||||
new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
myEnigma = new Enigma(tickPos, initialPos, permu, PATCHBOARDPERMU
|
||||
, REFLECTORPERMU);
|
||||
|
||||
|
||||
while (true) {
|
||||
String stdinp = br.readLine();
|
||||
if (stdinp.equals("")) {
|
||||
return;
|
||||
}
|
||||
int[] ciphertxt = convertCharInt(stdinp.toCharArray());
|
||||
if (!isEnigmaCharArray(ciphertxt)) {
|
||||
System.out.print("Error! Wrong input");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < ciphertxt.length; i++) {
|
||||
System.out.print(convertIntChar(myEnigma.encode(ciphertxt[i])));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user