Refactoring this Enigma cipher program
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3

Thread: Refactoring this Enigma cipher program

Hybrid View

  1. #1
    Join Date
    Dec 2013
    Posts
    75

    Refactoring this Enigma cipher program

    Hi fellow programmers!

    I was looking through a few old programs I wrote, and I came across this Enigma cipher simulator. I was wondering if you could help me refactor the algorithm, as it doesn't seem to be the most efficient method.

    Thanks for all the help!

    Lexi
    Attached Files Attached Files

  2. #2
    Join Date
    Dec 2012
    Location
    England
    Posts
    2,847

    Re: Refactoring this Enigma cipher program

    Try this. I've basically kept your algorithm but tidyied it up a bit. It will now deal with non-uppercase and digits in the text. Lowercase are converted to uppercase and other chars are kept the same in the output. I've separated out the various encoding strings (Alphabet, Reflector, Plugboard) so that it is now easier to change them if required as they are not now buried in a class.

    Code:
    #include <iostream>
    #include <string>
    #include <cctype>
    using namespace std;
    
    class Rotor
    {
    public:
    	Rotor(char pos = 0);
    
    	void SetRotorPosition(int NewPos);
    	void AdvanceRotor(int Steps);
    	void ReverseRotor(int Steps);
    	int GetSteps() const;
    	char GetCurrentCharacter()const;
    	char GetCharacterIndex(int Index)const;
    	char GetCharacterInverse(int i) const;
    
    private:
    	int CurPos;
    	int steps;
    };
    
    class Enigma
    {
    public:
    	Enigma(char r1, char r2, char r3, char r4, char r5) {
    		R[0] = r1;
    		R[1] = r2;
    		R[2] = r3;
    		R[3] = r4;
    		R[4] = r5;
    	}
    
    	~Enigma(){}
    
    	string Encrypt(const string& cleartext);
    
    	static int CharacterMap(char the_char);
    
    	static const char *Alphabet;
    	static const char *Reflector;
    	static const char *Plugboard;
    	static const int no_chars;
    
    private:
    	char plugboard(char Char);
    	Rotor R[5];
    };
    
    
    Rotor::Rotor(char pos) : CurPos(0), steps(0) 
    {
    	SetRotorPosition(Enigma::CharacterMap(pos));
    }
    
    int Rotor::GetSteps() const
    {
    	return steps;
    }
    
    void Rotor::ReverseRotor(int Steps)
    {
    	AdvanceRotor(-Steps);
    }
    
    char Rotor::GetCurrentCharacter() const
    {
    	return Enigma::Alphabet[CurPos];
    }
    
    char Rotor::GetCharacterIndex(int Index) const
    {
    	return Enigma::Alphabet[(CurPos + Index) % Enigma::no_chars];
    }
    
    char Rotor::GetCharacterInverse(int i) const
    {
    	return (i >= CurPos) ? Enigma::Alphabet[i - CurPos] : Enigma::Alphabet[Enigma::no_chars + i - CurPos];
    }
    
    void Rotor::SetRotorPosition(int NewPos)
    {
    	while (NewPos < 0)
    		NewPos += Enigma::no_chars;
    
    	CurPos = NewPos % Enigma::no_chars;
    	steps = 0;
    }
    
    void Rotor::AdvanceRotor(int Steps)
    {
    	CurPos += Steps;
    	while (CurPos < 0)
    		CurPos += Enigma::no_chars;
    
    	CurPos %= Enigma::no_chars;
    	steps += Steps % Enigma::no_chars;
    }
    
    //Returns index into Alphabet of the_char
    int Enigma::CharacterMap(char the_char)
    {
    char *p = strchr(Alphabet, the_char);
    
    	return p ? (int)(p - Alphabet) : no_chars;
    }
    
    //Returns corresponding char from plugboard for Char
    char Enigma::plugboard(char Char)
    {
    	if (isalpha(Char))
    		return (Plugboard[toupper(Char) - 'A']);
    
    	if (isdigit(Char))
    		return (Plugboard[Char - '0' + 26]);
    
    	//Return bad char
    	return ' ';
    }
    
    //Encrypt string
    string Enigma::Encrypt(const string& cleartext)
    {
    string ciphertext;
    
    	ciphertext.resize(cleartext.size());
    
    	for (size_t i = 0; i < cleartext.length(); i++) {
    		 int vali = CharacterMap(plugboard(cleartext[i]));
    		 char valc;
    
    		if (vali < no_chars) {
    			for (int r = 0; r <= 4; r++) {
    				valc = R[r].GetCharacterIndex(vali);
    				vali = CharacterMap(valc);
    			}
    
    			valc = Reflector[vali];
    			vali = CharacterMap(valc);
    
    			for (int r = 4; r >= 0; r--) {
    				valc = R[r].GetCharacterInverse(vali);
    				vali = CharacterMap(valc);
    			}
    
    			ciphertext[i] = plugboard(valc);
    
    			for (int r = 0; r <= 4; r++) {
    				R[r].AdvanceRotor(1);
    				if ((R[r].GetSteps() % no_chars) != 0)
    					break;
    			}
    
    		} else {
    			//cout << "bad val: " << vali << endl;
    			ciphertext[i] = cleartext[i];
    		}
    	}
    
    	return ciphertext;
    }
    
    const char* Enigma::Alphabet =  "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    const char* Enigma::Reflector = "COAYIWV7E3809TBUZ26NPGF4DQL5RJX1SHKM";
    const char *Enigma::Plugboard = "0QWEDTYUIOPSNMJKBZLFHXCVGRA987654321";
    const int Enigma::no_chars = (int)strlen(Enigma::Alphabet);
    
    int main()
    {
    char opt;
    
    	do {
    		char R1, R2, R3, R4, R5;
    		string ciphertext;
    
    		cout << "Enter the 5 rotor settings: ";
    		cin >> R1 >> R2 >> R3 >> R4 >> R5;
    
    		Enigma encryptor(R1, R2, R3, R4, R5);
    
    		cin.ignore(100, '\n');
    		cout << "Enter text: ";
    		getline(cin, ciphertext);
    		cout << "Ciphertext: " << encryptor.Encrypt(ciphertext) << endl;
    
    		do {
    			cout << "[A]gain or [Q]uit: ";
    			cin >> opt;
    			if ((opt = (char)toupper(opt)) != 'Q' && opt != 'A')
    				cout << "Invalid option\n";
    
    		} while (opt != 'A' && opt != 'Q');
    	} while (opt == 'A');
    
    	return 0;
    }
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  3. #3
    Join Date
    Dec 2013
    Posts
    75

    Re: Refactoring this Enigma cipher program

    Thanks for the help!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center