///<inheritdoc/> public override string Run(string input, bool forward) { var output = new StringBuilder(); int indexer = 0; foreach (var c in input) { if (indexer == Key.Length) { indexer = 0; } var steps = Alphabet.IndexOf(Key[indexer]) * (forward ? 1 : -1); output.Append(Alphabet.WrapChar(c, steps)); indexer++; } return(output.ToString()); }
/// <summary> /// A special run for the Enigma. Simulates a key press and returns a result. /// </summary> /// <param name="input">The character that has been depressed</param> /// <returns>The output, i.e the character that will be lit in the lamp</returns> public virtual char Run(char input) { //Rotate the FastRotor Rotors[0].Rotate(); //Get the index of the letter in the alphabet: int index = Alphabet.IndexOf(input); //Pass the current to the Stator: index = Stator.GetPath(index, true); //Pass the current through successive rotors: for (int i = 0; i < Rotors.Count; i++) { index = Rotors[i].GetPath(index, true); } //Pass the current the Reflector index = Reflector.GetPath(index, true); //Pass through the rotors in reverse: for (int i = Rotors.Count - 1; i > -1; i--) { var rotor = Rotors[i]; index = rotor.GetPath(index, false); } //Pass the current through the Stator: index = Stator.GetPath(index, false); var result = Alphabet[index]; //perform plugboard simulation: if (Plugboard != null) { result = Plugboard.Simulate(result); } return(result); }
public static EnigmaMachine Load(Stream stream) { using var reader = new BinaryReader(stream); //HEADER var buffer = reader.ReadString(); if (buffer != "EGMC") { throw new FormatException("Not a valid Enigma Machine File"); } //ALPHABET buffer = reader.ReadString(); if (buffer != "alph") { throw new FormatException("Not a valid Enigma Machine File"); } var len = reader.ReadInt32(); buffer = reader.ReadString(); var alphabet = new Alphabet(buffer); //AUTORESET var autroreset = reader.ReadBoolean(); //STATOR AND REFLECTOR var list = new string[] { "ETW ", "UKW " }; var wheels = new List <EnigmaWheel>(2); foreach (var item in list) { buffer = reader.ReadString(); if (buffer != item) { throw new FormatException("Not a valid Enigma Machine File"); } buffer = reader.ReadString(); if (buffer != "indx") { throw new FormatException("Not a valid Enigma Machine File"); } len = reader.ReadInt32(); buffer = reader.ReadString(); var indexing = new Alphabet(buffer); buffer = reader.ReadString(); if (buffer != "wire") { throw new FormatException("Invalid/Corrupted Enigma File"); } len = reader.ReadInt32(); buffer = reader.ReadString(); var wiring = new Alphabet(buffer); var wheel = new EnigmaWheel(indexing, wiring); wheels.Add(wheel); } //ROTORS buffer = reader.ReadString(); if (buffer != "ROTS") { throw new FormatException("Invalid/Corrupted Enigma File"); } len = reader.ReadInt32(); var builder = new StringBuilder(); var rotors = new List <Rotor>(); while (true) { builder.Clear(); buffer = reader.ReadString(); if (buffer != "indx") { throw new FormatException("Invalid/Corrupted Enigma File"); } len = reader.ReadInt32(); buffer = reader.ReadString(); var indexing = new Alphabet(buffer); buffer = reader.ReadString(); if (buffer != "wire") { throw new FormatException("Invalid/Corrupted Enigma File"); } len = reader.ReadInt32(); buffer = reader.ReadString(); var wiring = new Alphabet(buffer); var wheel = new EnigmaWheel(indexing, wiring); buffer = reader.ReadString(); if (buffer != "ntch") { throw new FormatException("Invalid/Corrupted Enigma File"); } len = reader.ReadInt32(); for (int t = 0; t < len; t++) { builder.Append(reader.ReadChar()); } var rotor = new Rotor(indexing, wiring, builder.ToString()); rotors.Add(rotor); if (reader.PeekChar() == -1) { break; } } //BUILDER return(new EnigmaMachineBuilder() .WithAlphabet(alphabet) .WithRotors(rotors) .WithStator(wheels[0]) .WithReflector(wheels[1]) .Build()); }
public void Save(Stream stream) { //header using var writer = new BinaryWriter(stream); //Header writer.Write("EGMC"); //Alphabet writer.Write("alph"); writer.Write(Alphabet.Count); writer.Write(Alphabet.ToString()); //Whether we autoreset writer.Write(AutoReset); //Stator Indexing: writer.Write("ETW "); writer.Write("indx"); writer.Write(Stator.Indexing.Count); writer.Write(Stator.Indexing.ToString()); //Stator Wiring writer.Write("wire"); writer.Write(Stator.Wiring.Count); writer.Write(Stator.Wiring.ToString()); //Reflector Indexing writer.Write("UKW "); writer.Write("indx"); writer.Write(Reflector.Indexing.Count); writer.Write(Reflector.Indexing.ToString()); //Reflector Wiring writer.Write("wire"); writer.Write(Reflector.Wiring.Count); writer.Write(Reflector.Wiring.ToString()); //Rotors writer.Write("ROTS"); writer.Write(Rotors.Count); foreach (var rotor in Rotors) { //Indexing writer.Write("indx"); writer.Write(rotor.Indexing.Count); writer.Write(rotor.Indexing.ToString()); //Wiring writer.Write("wire"); writer.Write(rotor.Wiring.Count); writer.Write(rotor.Wiring.ToString()); //Turnover Notch writer.Write("ntch"); writer.Write(rotor.TurnOver.Count); foreach (var notch in rotor.TurnOver) { writer.Write(notch); } } }
/// <summary> /// Creates a rotor from the specified configuration /// </summary> /// <param name="indexing">The index etching/></param> /// <param name="wiring">The wiring etching</param> /// <param name="turnOvers">A string, each <see cref="char"/> representing a turnover point</param> public Rotor(Alphabet indexing, Alphabet wiring, string turnOvers) : base(indexing, wiring) { TurnOver = new List <char>(turnOvers); }
///<inheritdoc/> public override string Run(string input, bool forward) { var keytable = new Alphabet(Alphabet.ToString()) { Dimensions = Alphabet.Dimensions }; var distinct = Key.Distinct().ToList(); for (int i = 0; i < distinct.Count; i++) { keytable.Move(distinct[i], i); } if (input.Length % 2 != 0) { input += Alphabet[Alphabet.Count - 1]; } var multiplier = forward ? 1 : -1; var output = new StringBuilder(); //Let the ciphering begin: for (int i = 0; i < input.Length; i += 2) { var a = keytable.DimensionsOf(input[i]); var b = keytable.DimensionsOf(input[i + 1]); var newA = new Dimensions(b.X, a.Y); var newB = new Dimensions(a.X, b.Y); if (a.X == b.X || a.Y == b.Y) { newA = a; newB = b; //SamePoint if (a == b) { newA.X = PrefferredOrientation == PrefferredOrientation.Horizontal ? newA.X += multiplier : newA.X; newA.Y = PrefferredOrientation == PrefferredOrientation.Vertical ? newA.Y += multiplier : newA.Y; newB = new Dimensions(newA.X, newA.Y); } //SameCol else if (a.X == b.X) { newA.Y += multiplier; newB.Y += multiplier; } //SameRow else { newA.X += multiplier; newB.X += multiplier; } newA.Limit(keytable.Dimensions); newB.Limit(keytable.Dimensions); } output.Append(keytable[newA]); output.Append(keytable[newB]); } return(output.ToString()); }
///<inheritdoc/> public Rotor(Alphabet indexing, Alphabet wiring) : base(indexing, wiring) { }
/// <summary> /// The alphabet to be used, in the machine and by the builder when creating the rotors and stators. /// When not provided, the default <see cref="Alphabets.ASCII"/> is used. /// </summary> /// <param name="alphabet"></param> /// <returns></returns> public EnigmaMachineBuilder WithAlphabet(Alphabet alphabet) { _alphabet = alphabet; return(this); }
/// <summary> /// Builds an <see cref="EnigmaMachine"/> with the provided parameters. /// </summary> /// <returns></returns> public EnigmaMachine Build() { var shuffle = new Alphabet(_alphabet.ToString()); //the stator: var stator = _stator; if (stator == null) { stator = new EnigmaWheel(_alphabet.ToString(), _alphabet.ToString()); } //the reflector var reflector = _reflector; if (reflector == null) { shuffle.Shuffle(); reflector = new EnigmaWheel(_alphabet.ToString(), shuffle.ToString()); reflector.Reflect(); } //the rotors List <Rotor> rotors; if (_rotors == null) { rotors = new List <Rotor>(); for (int i = 0; i < _rotorCount; i++) { string notches = ""; for (int n = 0; n < _notchCount; n++) { char c; do { int rnd = Horus.Random(0, _alphabet.Count); c = _alphabet[rnd]; } while (notches.Contains(c)); notches += c; } shuffle.Shuffle(); var rotor = new Rotor(_alphabet.ToString(), shuffle.ToString(), notches); rotors.Add(rotor); } } else { rotors = new List <Rotor>(_rotors); } //the actual construction return(new EnigmaMachine(rotors) { Alphabet = _alphabet, AutoReset = _autoReset, Stator = stator, Reflector = reflector, }); }
/// <summary> /// Creates a wheel from the specified indexing and wiring /// </summary> /// <param name="indexing">The index etchings</param> /// <param name="wiring">The scrambled of the indexing</param> public EnigmaWheel(string indexing, string wiring) { Indexing = new Alphabet(indexing); Wiring = new Alphabet(wiring); }
/// <summary> /// Creates a wheel from the specified indexing and wiring /// </summary> /// <param name="indexing">The index etchings</param> /// <param name="wiring">The scrambled of the indexing</param> public EnigmaWheel(Alphabet indexing, Alphabet wiring) { Indexing = indexing; Wiring = wiring; }