234 lines
6.5 KiB
Java
Executable File
234 lines
6.5 KiB
Java
Executable File
package de.vanitasvitae.enigmandroid;
|
|
|
|
|
|
import de.vanitasvitae.enigmandroid.rotors.Reflector;
|
|
import de.vanitasvitae.enigmandroid.rotors.Rotor;
|
|
|
|
/**
|
|
* Enigma-machine
|
|
*Copyright (C) 2015 Paul Schaub
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
* @author vanitasvitae
|
|
*/
|
|
public class Enigma
|
|
{
|
|
private Plugboard plugboard;
|
|
|
|
//Slots for the rotors
|
|
private Rotor r1;
|
|
private Rotor r2;
|
|
private Rotor r3;
|
|
|
|
//Slot for the reflector
|
|
private Reflector reflector;
|
|
|
|
private boolean doAnomaly = false;
|
|
|
|
private boolean prefAnomaly; //Do you want to simulate the anomaly?
|
|
|
|
/**
|
|
* Create new Enigma with standard configuration.
|
|
* Empty Plugboard, rotors I,II,III, Positions 0,0,0
|
|
*/
|
|
public Enigma()
|
|
{
|
|
initialize();
|
|
}
|
|
|
|
private void initialize()
|
|
{
|
|
this.r1 = Rotor.createRotorI(0, 0);
|
|
this.r2 = Rotor.createRotorII(0, 0);
|
|
this.r3 = Rotor.createRotorIII(0, 0);
|
|
this.reflector = Reflector.createReflectorB();
|
|
plugboard = new Plugboard();
|
|
prefAnomaly = true;
|
|
}
|
|
|
|
/**
|
|
* Encrypt / Decrypt a given String
|
|
*
|
|
* @param w Text to decrypt/encrypt
|
|
* @return encrypted/decrypted string
|
|
*/
|
|
public String encrypt(String w)
|
|
{
|
|
//output string
|
|
String output = "";
|
|
//for each char x in k
|
|
for (char x : w.toCharArray())
|
|
{
|
|
output = output + this.encryptChar(x);
|
|
}
|
|
//return en-/decrypted string
|
|
return output;
|
|
}
|
|
|
|
/**
|
|
* Perform crypto on char.
|
|
* Beforehand rotate rotors. Also implement the rotor anomaly.
|
|
*
|
|
* @param k input char
|
|
* @return output char
|
|
*/
|
|
public char encryptChar(char k)
|
|
{
|
|
//Rotate rotors
|
|
r1.rotate();
|
|
if (r1.isAtTurnoverPosition() || (this.doAnomaly && prefAnomaly))
|
|
{
|
|
r2.rotate();
|
|
//Handle Anomaly
|
|
this.doAnomaly = r2.doubleTurnAnomaly();
|
|
if (r2.isAtTurnoverPosition())
|
|
{
|
|
r3.rotate();
|
|
}
|
|
}
|
|
int x = (int) k;
|
|
x = x - 65; //Remove Unicode Offset (A=65 in Unicode.)
|
|
|
|
//Encryption
|
|
//forward direction
|
|
x = plugboard.encrypt(x);
|
|
x = normalize(x + r1.getRotation());
|
|
x = r1.encryptForward(x);
|
|
x = normalize(x + r2.getRotation() - r1.getRotation());
|
|
x = r2.encryptForward(x);
|
|
x = normalize(x + r3.getRotation() - r2.getRotation());
|
|
x = r3.encryptForward(x);
|
|
x = normalize(x - r3.getRotation());
|
|
//backward direction
|
|
x = reflector.encrypt(x);
|
|
x = normalize(x + r3.getRotation());
|
|
x = r3.encryptBackward(x);
|
|
x = normalize(x - r3.getRotation() + r2.getRotation());
|
|
x = r2.encryptBackward(x);
|
|
x = normalize(x - r2.getRotation() + r1.getRotation());
|
|
x = r1.encryptBackward(x);
|
|
x = normalize(x - r1.getRotation());
|
|
x = plugboard.encrypt(x);
|
|
|
|
return (char) (x + 65); //Add Offset
|
|
}
|
|
|
|
public int normalize(int input)
|
|
{
|
|
return (26+input)%26;
|
|
}
|
|
|
|
/**
|
|
* Prepare String for encryption via enigma
|
|
* Replace . , ! ? : with X
|
|
* Remove all other chars that are not A..Z
|
|
*
|
|
* @param word string
|
|
* @return prepared string
|
|
*/
|
|
public static String prepare(String word)
|
|
{
|
|
String input = word.toUpperCase();
|
|
String output = "";
|
|
for (char x : input.toCharArray())
|
|
{
|
|
if (x >= 65 && x <= 90) //If x in [A..Z]
|
|
{
|
|
output = output + x; //Append to String
|
|
}
|
|
//if x is special symbol
|
|
else
|
|
{
|
|
if (x == '.' || x == ',' || x == '!' || x == '?' || x == ':')
|
|
{
|
|
//replace x with X and encrypt
|
|
output = output + 'X';
|
|
}
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
/**
|
|
* Set config of the enigma
|
|
*
|
|
* @param conf configuration
|
|
*/
|
|
public void setConfiguration(int[] conf)
|
|
{
|
|
if (conf == null || conf.length != 10)
|
|
{
|
|
initialize();
|
|
}
|
|
else
|
|
{
|
|
int ro1 = conf[0];
|
|
int ro2 = conf[1];
|
|
int ro3 = conf[2];
|
|
int ref = conf[3];
|
|
int ro1rot = normalize(conf[4] - 1);
|
|
int ro2rot = normalize(conf[5] - 1);
|
|
int ro3rot = normalize(conf[6] - 1);
|
|
int ro1Ring = conf[7];
|
|
int ro2Ring = conf[8];
|
|
int ro3Ring = conf[9];
|
|
|
|
//Set rotors
|
|
r1 = Rotor.createRotor(ro1, ro1Ring, ro1rot);
|
|
r2 = Rotor.createRotor(ro2, ro2Ring, ro2rot);
|
|
r3 = Rotor.createRotor(ro3, ro3Ring, ro3rot);
|
|
|
|
//Set reflector
|
|
reflector = Reflector.createReflector(ref);
|
|
|
|
//catch double turn anomaly on step by step basis
|
|
this.doAnomaly = r2.doubleTurnAnomaly();
|
|
}
|
|
}
|
|
|
|
public void setPlugboard(Plugboard p)
|
|
{
|
|
this.plugboard = p;
|
|
}
|
|
|
|
/**
|
|
* Return the configuration, the enigma machine is in right NOW
|
|
*
|
|
* @return array containing configuration
|
|
*/
|
|
public int[] getConfiguration()
|
|
{
|
|
int[] configuration = new int[10];
|
|
{
|
|
configuration[0] = r1.getType();
|
|
configuration[1] = r2.getType();
|
|
configuration[2] = r3.getType();
|
|
configuration[3] = reflector.getType();
|
|
configuration[4] = r1.getRotation();
|
|
configuration[5] = r2.getRotation();
|
|
configuration[6] = r3.getRotation();
|
|
configuration[7] = r1.getRingSetting();
|
|
configuration[8] = r2.getRingSetting();
|
|
configuration[9] = r3.getRingSetting();
|
|
}
|
|
return configuration;
|
|
}
|
|
|
|
public void setPrefAnomaly(boolean b)
|
|
{
|
|
this.prefAnomaly = b;
|
|
}
|
|
}
|