Page 1 of 1

Enigma Machine simulate the encryption capabilities of the germans in WWII Rate Topic: -----

#1 potator  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 5
  • View blog
  • Posts: 84
  • Joined: 02-December 07

Posted 06 March 2008 - 10:12 PM

I originally uploaded this in a forum and because some people are afraid of downloading something they don't know, I was forced to make this a tutorial.

The following changes have been made from the previous versions:
Logic errors in the inverter flip method corrected.
Rotor class simplified.
Enigma class made more versatile

The older versions can be seen here.

As always, the documentation comments are in. So if you have an environment that can generate a javadoc, you're good to go.

To code an enigma machine, we must first dissect what the Enigma machine does. (source wikipedia) The Enigma machine was made up of a typewriter like device equipped with a number of rotors that each performed a simple substitution encryption. Each time you pressed a key, the system would send an electrical signal through each of the rotors in turn and then an inverter. The inverter sent the electrical signal back through the rotors in the opposite direction. The outputted signal would be the encrypted character. When the depressed key was released, another mechanical part of machine turned one, some, or all of the rotors (based on the rotors themselves) therefore changing the cipher for each new character. The major flaw in this algorithm is that any given character can never be encoded to itself (i.e. type in "e" and the output is "e")

What makes this encryption system robust is that rotors can be set to different values before the encryption takes place. The number of combinations can be daunting. What makes this one of the most interesting ciphers I've worked with though, is the inverter. The inverter makes the enigma machine amazing. Without it, decoding would mean flipping all the rotors around and rotating them in the opposite direction. The inverter makes it so that if you set the machine to values 1,2,3,4 when you are encrypting, you can set the machine to 1,2,3,4 for decrypting the message as well. It just makes implementation easier.

So, now to the fun part: data structures.
Rotor:
The rotor needs to be able to perform a simple substitution encryption in both directions. It also needs to be able to be set to a specific 'value' before encrypting or decrypting. It needs to be able to change it's encryption regularly and have a variable that tells it when it's time to rotate.

here is how substitution works; you start with two strings of text:

abcdefg
gdbefac

So if you input "a" the output is "g" if you're going forward.
The output is "f" when the input is "a" if you're going in reverse. Get it?

To change the cipher consistantly, I changed each letter to the letter following it. (replacing 'Z" with 'A') This shows the iterations:

initial:
abcdefg
gdbefac

changed1:
bcdefga
aecfgbd

changed2:
cdefgab
bfdgace

And so on. To tell when it is time to rotate, I simply kept track of a integer representing the frequency at which I wanted it to rotate.
The following is the Rotor class:
package beast;

import java.lang.reflect.MalformedParameterizedTypeException;
/**
 * Represents a dynamic rotor capable of simple substitution in an enigma machine.
 * A rotor has 40 positions.
 * @author Colter LeSage
 */
public class Rotor {
	private static final String string2 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ .?!";
	/**
	 * One of many standard rotors ready to use right out of the box. 
	 */
	public static final Rotor ROTOR_I = new Rotor(1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789. !?");
	/**
	 * One of many standard rotors ready to use right out of the box. 
	 */
	public static final Rotor ROTOR_II = new Rotor(8,"0P9OL8IK7UJM6YHN5TGB4?RFV3!EDC2WSX1QAZ. ");
	/**
	 * One of many standard rotors ready to use right out of the box. 
	 */
	public static final Rotor ROTOR_III = new Rotor(13,"QWERTPOIUY1029384756ASDFLKJHG. !?ZXCMNBV");
	/**
	 * One of many standard rotors ready to use right out of the box. 
	 */
	public static final Rotor ROTOR_IV = new Rotor(6,"ISX1QJM6YHN5TGAZ. K7U?RFV3!EDC2WB0P9OL84");
	/**
	 * One of many standard rotors ready to use right out of the box. 
	 */
	public static final Rotor ROTOR_V = new Rotor(2,"WA2Q1GV6PL. N8UHX40OK?M9B7YESZ3TFC5RDIJ!");
	
	private String string1;
	private int rotations;
	private int frequency;
	
	/**
	 * @param i determines how often the rotor rotates.  Variety is desired for more robust encryptions.
	 * @param a a String containing all letters of the alphabet, the numbers from 0 to 9, a space, a period, an exclamation point, and a question mark
	 */
	public Rotor(int i,String a) throws MalformedParameterizedTypeException{
		string1 = a.toUpperCase();rotations = 0;frequency = i;
		for(char x = 'A'; x < 'Z' + 1; x++){
			if(string1.indexOf(x) < 0)
				throw new MalformedParameterizedTypeException();
		}
		for(char x = '0'; x < '9' + 1; x++){
			if(string1.indexOf(x) < 0)
				throw new MalformedParameterizedTypeException();
		}
		if(string1.indexOf('.') < 0)throw new MalformedParameterizedTypeException();
		if(string1.indexOf(' ') < 0)throw new MalformedParameterizedTypeException();
		if(string1.indexOf('?') < 0)throw new MalformedParameterizedTypeException();
		if(string1.indexOf('!') < 0)throw new MalformedParameterizedTypeException();
		if(frequency < 1)throw new MalformedParameterizedTypeException();
	}

	/**
	 * Positions the rotor at a desired location
	 * @param i an int typically between 0 an 39
	 */
	public void position(int i){
		for(int x = 0; x < rotations; x++)rotate(-1);
		for(int x = 0; x < i; x++)rotate(1);
	}
	
	/**
	 * Sends a char through the substitution algorhythm
	 * @param c the char to be converted
	 * @param direction 1 or -1 depending on whether moving toward or away from the inverter
	 * @return an encrypted char
	 */
	public char chug(char c, int direction){
		if(direction == 1)
			return string2.charAt(string1.indexOf(c));
		else
			return string1.charAt(string2.indexOf(c));
	}
	
	/**
	 * rotates the rotor once
	 */
	public void rotate(){
		rotate(1);
	}

	private void rotate(int direction){
		if(direction == 1){
			string1.replace('Z', '~');
			string2.replace('Z', '~');
			for(char x = 'A'; x < 'Z'; x++){
				string1.replace(x, (char)(x + 1));
				string2.replace(x, (char)(x + 1));
			}
			string1.replace('~', 'A');
			string2.replace('~', 'A');
			rotations += 1;
		}
		else if(direction == -1){
			string1.replace('A', '~');
			string2.replace('A', '~');
			for(char x = 'B'; x <= 'Z'; x++){
				string1.replace(x, (char)(x - 1));
				string2.replace(x, (char)(x - 1));
			}
			string1.replace('~', 'Z');
			string2.replace('~', 'Z');
			rotations -= 1;
		}
		if(rotations > 39) rotations = 0;
		if(rotations < 0) rotations = 39;
	}

	/**
	 * Get the position of the rotor
	 * @return the current position of the rotor (0 to 39)
	 */
	public int getOrientation(){
		return rotations;
	}
	/**
	 * Get the frequency at which the rotor turns
	 * @return the frequency at which the rotor turns
	 */
	public int getFrequency(){
		return frequency;
	}
}



Inverter:
Although later models of the enigma machine had rotating inverters, I chose to have a fixed one for more simplicity. My inverter uses only one line of text, matching characters that are the same distance from both ends. For example:

ABCDEFGH

'A' would be encoded to 'H' and 'H' would be encoded to 'A'. 'B' would be paired with 'G' and so on. My inverter, like the original, allows 2 different positions. To change positions, the first half of the key is reversed. So:
ABCDEFGH
becomes
DCBAEFGH
and vise versa.

The following is the inverter class:
package beast;

import java.lang.reflect.MalformedParameterizedTypeException;

/**
 * Represents digitially a stationary inverter in an enigma machine.
 * An inverter has has two positions.
 * @author Colter LeSage
 */
public class Inverter {
	
	/**
	 * A standard inverter ready to use right out of the box. 
	 */
	public static final Inverter STANDARD_INVERTER = new Inverter("QPWOE?IRUTYLA KSJDHFGZM.XNCBV1!029384756");
	
	private String key;
	private int orientation;
	
	/**
	 * @param s a String containing all letters of the alphabet, the numbers from 0 to 9, a space, a period, an exclamation point, and a question mark
	 */
	public Inverter(String s){
		key = s.toUpperCase();
		for(char x = 'A'; x < 'Z' + 1; x++){
			if(key.indexOf(x) < 0)
				throw new MalformedParameterizedTypeException();
		}
		for(char x = '0'; x < '9' + 1; x++){
			if(key.indexOf(x) < 0)
				throw new MalformedParameterizedTypeException();
		}
		if(key.indexOf('.') < 0)throw new MalformedParameterizedTypeException();
		if(key.indexOf(' ') < 0)throw new MalformedParameterizedTypeException();
		if(key.indexOf('?') < 0)throw new MalformedParameterizedTypeException();
		if(key.indexOf('!') < 0)throw new MalformedParameterizedTypeException();
		
		orientation = 1;
	}
	
	/**
	 * "flips" the inverter between it's two states; 1 and -1
	 */
	public void flip(){
		orientation = -orientation;
		StringBuffer firstHalf = new StringBuffer(key.substring(0, 20));
		key = (firstHalf.reverse()).toString() + key.substring(20, 40);
	}
	
	/**
	 * @return returns either 1 or -1 based on the inverter's position
	 */
	public int getOrientation(){
		return orientation;
	}
	
	/**
	 * @param c char to be sent through the inverter
	 * @return the char that the input char is paired with
	 */
	public char chug(char c){
		return key.charAt(39 - key.indexOf(c));
	}
}



Enigma:
The enigma machine is really (in JAVA) a collection of rotors and and inverter. I wont bother trying to explain all the implementation. Basically it plugs values into the rotors and inverter in the correct order. Then it checks to see if the rotors need to be turned and turns the ones that do.
package beast;

import java.lang.reflect.MalformedParameterizedTypeException;

/**
 * Digitally emulates an Enigma machine containing any number of rotors and one inverter
 * @author Colter LeSage
 */
public class Enigma {
	private Rotor[] rotors;
	private Inverter inverter;
	private static int count;
	
	/**
	 * @param r an array whose length represents how many rotors are present in this enigma machine
	 * @param d the inverter
	 */
	public Enigma(Rotor[] r, Inverter d){
		rotors = r; inverter = d;
	}
	
	/**
	 * @param r an array that represents values for rotors followd by the value for the inverter
	 * @throws MalformedParameterizedTypeException
	 */
	public void set(int[] r) throws MalformedParameterizedTypeException{
		boolean ok = true;
		for(int x = 0; x < r.length - 1; x++)if(r[x] > 39 || r[x] < 0)ok = false;
		if(r.length != rotors.length + 1)ok = false;
		if(ok && (r[r.length - 1] == 1 || r[r.length - 1]  == -1)){
			for(int x = 0; x < rotors.length; x++)
				rotors[x].position(r[x]);
			if(inverter.getOrientation() != r[r.length - 1])inverter.flip();
		}
		else
			throw new MalformedParameterizedTypeException();
	}
	
	/**
	 * Encrypts plaintext using the current rotor/inverter configuration.
	 * @param plaintext the text to be converted
	 * @return the ciphertext (encrypted message) Note:messages are always converted to all caps
	 */
	public String encrypt(String plaintext){
		plaintext = plaintext.toUpperCase();
		String ciphertext = "";
		for(count = 0; count < plaintext.length(); count++)
			ciphertext += chug(plaintext.charAt(count));
		return ciphertext;
	}
	
	/**
	 * Deciphers encrypted messages
	 * @param ciphertext the encrypted message
	 * @return plaintext (decrypted message)
	 */
	public String decrypt(String ciphertext){
		return encrypt(ciphertext);
	}
	
	private char chug(char c){
		for(int x = 0; x < rotors.length; x++)
			c = rotors[x].chug(c, 1);
		c = inverter.chug(c);
		for(int x = rotors.length - 1; x > -1; x--)
			c = rotors[x].chug(c, -1);
		for(int x = 0; x < rotors.length; x++)
			if(count % rotors[x].getFrequency() == 0)rotors[x].rotate();
		return c;
	}
	
}



A note: these three classes need to be saved in a folder called "beast".

Here is a simple example of how to use the machine:
import beast.*;

public class tester {
	public static void main(String[] args){
		Rotor[] r = {Rotor.ROTOR_I, Rotor.ROTOR_II, Rotor.ROTOR_V, Rotor.ROTOR_IV, Rotor.ROTOR_III};
		int[] key = {17,9,34,22,6,-1};
		Enigma machine = new Enigma(r, Inverter.STANDARD_INVERTER);
		machine.set(key);
		String i = machine.encrypt("YOUR PRINCESS IS IN ANOTHER CASTLE");
		System.out.println(i);
		machine.set(key);
		i = machine.decrypt(i);
		System.out.println(i);
	}
}


Save this file somewhere where it has access to the beast folder.

Last, but not least, I leave you with all of the files with documentation in a zipped folder (it contains the Eclipse project files too):

Attached File(s)



Is This A Good Question/Topic? 0
  • +

Replies To: Enigma Machine

#2 Amadeus  Icon User is offline

  • g+ + -o drink whiskey.cpp
  • member icon

Reputation: 248
  • View blog
  • Posts: 13,506
  • Joined: 12-July 02

Posted 11 March 2008 - 05:01 AM

Tutorial approved. As for your comment about some people being apprehensive about downloading something about which they have no information from someone about whom they have no information, that is simple internet security. Any beginning user should be mindful enough of security concerns to take simple precautions such as that.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1