EnigmAndroid/app/src/main/java/de/vanitasvitae/enigmandroid/Enigma.java

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