Skip to content

Instantly share code, notes, and snippets.

@jimbojetset
Created January 10, 2017 20:20
Show Gist options
  • Save jimbojetset/3ff02650899773ce3700213cc7a52689 to your computer and use it in GitHub Desktop.
Save jimbojetset/3ff02650899773ce3700213cc7a52689 to your computer and use it in GitHub Desktop.
Enigma Emulator c#
using System;
using System.Text;
using System.Diagnostics;
namespace Enigma
{
class EnigmaMachine
{
private const string _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static Tuple<string, int, int> _rotor_Blank = new Tuple<string, int, int>("ABCDEFGHIJKLMNOPQRSTUVWXYZ", -99, -99);
private static Tuple<string, int, int> _rotor_I = new Tuple<string, int, int>("EKMFLGDQVZNTOWYHXUSPAIBRCJ", 16, -99);
private static Tuple<string, int, int> _rotor_II = new Tuple<string, int, int>("AJDKSIRUXBLHWTMCQGZNPYFVOE", 4, -99);
private static Tuple<string, int, int> _rotor_III = new Tuple<string, int, int>("BDFHJLCPRTXVZNYEIWGAKMUSQO", 21, -99);
private static Tuple<string, int, int> _rotor_IV = new Tuple<string, int, int>("ESOVPZJAYQUIRHXLNFTGKDCMWB", 9, -99);
private static Tuple<string, int, int> _rotor_V = new Tuple<string, int, int>("VZBRGITYUPSDNHLXAWMJQOFECK", 25, -99);
private static Tuple<string, int, int> _rotor_VI = new Tuple<string, int, int>("JPGVOUMFYQBENHZRDKASXLICTW", 25, 12);
private static Tuple<string, int, int> _rotor_VII = new Tuple<string, int, int>("NZJHGRCXMYSWBOUFAIVLPEKQDT", 25, 12);
private static Tuple<string, int, int> _rotor_VIII = new Tuple<string, int, int>("FKQHTLXOCBJSPDZRAMEWNIUYGV", 25, 12);
private static Tuple<string, int, int> _rotor_b = new Tuple<string, int, int>("LEYJVCNIXWPBQMDRTAKZGFUHOS", -99, -99);
private static Tuple<string, int, int> _rotor_g = new Tuple<string, int, int>("FSOKANUERHMBTIYCWLQPZXVGJD", -99, -99);
private static string _reflector_Blank = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static string _reflector_A = "EJMZALYXVBWFCRQUONTSPIKHGD";
private static string _reflector_B = "YRUHQSLDPXNGOKMIEBFZCWVJAT";
private static string _reflector_C = "FVPJIAOYEDRZXWGCTKUQSBNMHL";
private static string _reflector_b = "ENKQAUYWJICOPBLMDXZVFTHRGS";
private static string _reflector_c = "RDOBJNTKVEHMLFCWZAXGYIPSUQ";
private static Rotor _rotor0;
private static Rotor _rotor1;
private static Rotor _rotor2;
private static Rotor _rotor3;
private static Reflector _reflector;
private static Plugboard _plugboard;
private static bool _readyToDecode = false;
public bool SetupEnigmaMachine(string setupValues)
{
try
{
string[] value = setupValues.Split(':');
if (value.Length == 6)
{
char reflector = value[0][0];
string reel = value[1];
string ring = value[2].ToUpper();
string pstn = value[3].ToUpper();
string plugboard = value[4].ToUpper();
_reflector = Create_Reflector(reflector);
_rotor0 = Create_Rotor(reel[0], ring[0], pstn[0]);
_rotor1 = Create_Rotor(reel[1], ring[1], pstn[1]);
_rotor2 = Create_Rotor(reel[2], ring[2], pstn[2]);
_rotor3 = Create_Rotor(reel[3], ring[3], pstn[3]);
_plugboard = Create_Plugboard(plugboard);
_readyToDecode = true;
return true;
}
else throw new Exception();
}
catch
{
_readyToDecode = false;
return false;
}
}
public string Transpose_CipherText(string cipherText)
{
if (_readyToDecode && cipherText.Length > 0)
{
StringBuilder plainText = new StringBuilder();
foreach (char keyValue in cipherText)
if (keyValue == ' ')
plainText.Append(' ');
else
{
int lampValue = KeyPress(_alpha.IndexOf(keyValue));
plainText.Append(_alpha[lampValue]);
}
return plainText.ToString();
}
return Help;
}
public static int KeyPress(int keyValue)
{
if (_readyToDecode)
{
RotateTheRotors();
int lampValue = GetLampValue(keyValue);
return lampValue;
}
return -99;
}
private static int GetLampValue(int keyValue)
{
int val = _plugboard.GetIndex(keyValue);
val = _rotor3.Transpose(val, Rotor.Path.Fwd);
val = _rotor2.Transpose(val, Rotor.Path.Fwd);
val = _rotor1.Transpose(val, Rotor.Path.Fwd);
val = _rotor0.Transpose(val, Rotor.Path.Fwd);
val = _reflector.GetIndex(val);
val = _rotor0.Transpose(val, Rotor.Path.Rev);
val = _rotor1.Transpose(val, Rotor.Path.Rev);
val = _rotor2.Transpose(val, Rotor.Path.Rev);
val = _rotor3.Transpose(val, Rotor.Path.Rev);
int lampValue = _plugboard.GetIndex(val);
return lampValue;
}
private static void RotateTheRotors()
{
if (_rotor2.IsNotched)
{
_rotor1.Rotate();
_rotor2.Rotate();
}
else if (_rotor3.IsNotched)
_rotor2.Rotate();
_rotor3.Rotate();
}
private static Reflector Create_Reflector(char reflector)
{
switch (reflector)
{
case '-':
return new Reflector(_reflector_Blank);
case 'A':
return new Reflector(_reflector_A);
case 'B':
return new Reflector(_reflector_B);
case 'C':
return new Reflector(_reflector_C);
case 'b':
return new Reflector(_reflector_b);
case 'c':
return new Reflector(_reflector_c);
}
throw new Exception();
}
private static Rotor Create_Rotor(char reel, char ring, char pstn)
{
switch (reel)
{
case '-':
return new Rotor(_rotor_Blank, 0, 0);
case '1':
return new Rotor(_rotor_I, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
case '2':
return new Rotor(_rotor_II, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
case '3':
return new Rotor(_rotor_III, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
case '4':
return new Rotor(_rotor_IV, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
case '5':
return new Rotor(_rotor_V, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
case '6':
return new Rotor(_rotor_VI, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
case '7':
return new Rotor(_rotor_VII, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
case '8':
return new Rotor(_rotor_VIII, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
case 'b':
return new Rotor(_rotor_b, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
case 'g':
return new Rotor(_rotor_g, _alpha.IndexOf(ring), _alpha.IndexOf(pstn));
}
throw new Exception();
}
private static Plugboard Create_Plugboard(string plugboardLinks)
{
_plugboard = new Plugboard();
string[] links = plugboardLinks.Split('-');
if (plugboardLinks.Length > 0)
foreach (string link in links)
_plugboard.Swap(_alpha.IndexOf(link[0]), _alpha.IndexOf(link[1]));
return _plugboard;
}
public string Help
{
get
{
StringBuilder errorMessage = new StringBuilder();
errorMessage.Append("Invalid arguments supplied.\n\n");
errorMessage.Append("Example 1 - B:-123:-ABC:-XYZ:AB-CD-EF:BLELDVPPFW\n(3 Rotor M3 Wehrmacht Enigma with plug settings)\n\n");
errorMessage.Append("Example 1 - B:-123:-ABC:-XYZ::SLFLPVPVEW\n(3 Rotor M3 Wehrmacht Enigma with no plug settings)\n\n");
errorMessage.Append("Example 2 - B:b123:AABC:AXYZ::\"NKIK UJQA RR\"\n(4 Rotor M4 Navy Enigma)\n\n");
errorMessage.Append(" Reeflector - B (A B C b c)\n");
errorMessage.Append(" Reels(left to right) - 123 ( 1 2 3 4 5 6 7 8 b g)\n");
errorMessage.Append(" Ring Position(left to right) - ABC\n");
errorMessage.Append(" Start Position(left to right) - XYZ\n");
errorMessage.Append(" Plugboard Wiring - AB-CD-EF (optional)\n");
errorMessage.Append(" Ciphertext can be entered as CIPHERTEXT or \"CIPH ERTE TX\"");
return errorMessage.ToString();
}
}
}
class Rotor
{
private string _pattern;
private string _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private int _notch1;
private int _notch2;
private int _reelPosition = 0;
private int _rsl = 0;
public enum Path { Fwd, Rev };
public Rotor(Tuple<string, int, int> rotor, int ringPos, int startPos)
{
_pattern = rotor.Item1;
_notch1 = rotor.Item2;
_notch2 = rotor.Item3;
_reelPosition = startPos;
_rsl = ringPos;
}
public bool IsNotched
{
get { return (_reelPosition == _notch1 || _reelPosition == _notch2); }
}
public void Rotate()
{
_reelPosition = (_reelPosition + 1) % 26;
}
public int Transpose(int x, Path dir)
{
x = (x + _reelPosition - _rsl + 26) % 26;
int t = GetIndex(x, dir) - _reelPosition + _rsl + 26;
return t % 26;
}
private int GetIndex(int x, Path dir)
{
if (dir == Path.Fwd)
return _alpha.IndexOf(_pattern[x]);
else
return _pattern.IndexOf(_alpha[x]);
}
}
class Reflector
{
private string _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private string _pattern;
public Reflector(string pattern)
{
_pattern = pattern;
}
public int GetIndex(int x)
{
return _pattern.IndexOf(_alpha[x]);
}
}
class Plugboard
{
public string _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public string _pattern = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public void Swap(int a, int b)
{
if (a != b && _alpha[a] == _pattern[a] && _alpha[b] == _pattern[b])
_pattern = _pattern.Replace(_alpha[a], '~').Replace(_pattern[b], _alpha[a]).Replace('~', _pattern[b]);
else throw new Exception();
}
public int GetIndex(int x)
{
return _pattern.IndexOf(_alpha[x]);
}
}
}
using System;
using Enigma;
class Program
{
private static EnigmaMachine enigma = new EnigmaMachine();
static void Main(string[] args)
{
if (args.Length == 1)
{
string[] values = args[0].Split(':');
if (values.Length == 6)
{
string cipherText = values[5].ToUpper();
if (enigma.SetupEnigmaMachine(args[0]))
{
Console.WriteLine(" IN: " + cipherText);
Console.WriteLine("");
Console.WriteLine("OUT: " + enigma.Transpose_CipherText(cipherText));
}
else
Console.WriteLine(enigma.Help);
}
else
Console.WriteLine(enigma.Help);
}
else
Console.WriteLine(enigma.Help);
Console.WriteLine("\nPress ANY Key To Exit");
Console.ReadKey();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment