My first C# class - please critique...

alank2

Member
Joined
Jan 10, 2019
Messages
6
Programming Experience
10+
Hi Everyone,

I took something I'm familiar with (German M4 Enigma encryption machine) and implemented it in what I hope is decent form/pattern C#. I've written this many times on many platforms in C/assembly/basic/etc. and it is sort of my "fizz bizz" of can I implement it in a new language. If you want to know about the Enigma, here is a great page with plenty of details:

https://www.cryptomuseum.com/crypto/enigma/m4/index.htm

So what I'm looking for is what C# improvements are there to be made. Being used to C/C++ I tend to think that way and not implement something in the proper way that a C# dev would. Let me know what I missed or did inefficiently.

program.cs
C#:
using System;using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;




namespace EnigmaTestApp
{
    class Program
    {
        static void ShowEnigmaState(Enigma enigma)
        {
            Console.WriteLine("REFL=" + enigma.Reflector);
            Console.WriteLine("ROTR=" + enigma.Rotors);
            Console.WriteLine("RING=" + enigma.Rings);
            Console.WriteLine("PLUG=" + enigma.Plugboard);
            Console.WriteLine("INDC=" + enigma.Indicators);
        }


        static void Main(string[] args)
        {
            string s1;
            Enigma enigma = new Enigma();


            enigma.Plugboard = "BE ZY";
            
            ShowEnigmaState(enigma);


            s1 = "AAAAA";
            Console.WriteLine();
            Console.WriteLine("IN:"+s1);


            s1 =enigma.Cipher(s1);
            Console.WriteLine("OUT:"+s1);
            Console.WriteLine();


            ShowEnigmaState(enigma);
        }
    }
}

enigma.cs
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace EnigmaTestApp
{
    class Enigma
    {
        const int POSITIONS = 26;
        const int ROTORS = 4;
        const int POS_STEP = 32;
        const int POS_ONLY = 31;


        enum rotorwiringnames
        {
            ROTOR_1M,
            ROTOR_2M,
            ROTOR_3M,
            ROTOR_4M,
            ROTOR_5M,
            ROTOR_6M,
            ROTOR_7M,
            ROTOR_8M,
            ROTOR_BETA,
            ROTOR_GAMMA,
            ROTOR_REFL4B,
            ROTOR_REFL4C,
        };


        static private readonly int[,] rotorwiring = new int[12, POSITIONS]
        {
            //"EKMFLGDQVZNTOWYHxUSPAIBRCJ", ROTOR_1M
            {4,10,12,5,11,6,3,16,21,25,13,19,14,22,24,7,23|POS_STEP,20,18,15,0,8,1,17,2,9,},


            //"AJDKsIRUXBLHWTMCQGZNPYFVOE", ROTOR_2M
            {0,9,3,10,18|POS_STEP,8,17,20,23,1,11,7,22,19,12,2,16,6,25,13,15,24,5,21,14,4,},


            //"BDFHJLCPRTXVZNYEIWGAKmUSQO", ROTOR_3M
            {1,3,5,7,9,11,2,15,17,19,23,21,25,13,24,4,8,22,6,0,10,12|POS_STEP,20,18,16,14,},


            //"ESOVPZJAYqUIRHXLNFTGKDCMWB", ROTOR_4M
            {4,18,14,21,15,25,9,0,24,16|POS_STEP,20,8,17,7,23,11,13,5,19,6,10,3,2,12,22,1,},


            //"VZBRGITYUPSDNHLXAWMJQOFECk", ROTOR_5M
            {21,25,1,17,6,8,19,24,20,15,18,3,13,7,11,23,0,22,12,9,16,14,5,4,2,10|POS_STEP,},


            //"JPGVOUMFYQBEnHZRDKASXLICTw", ROTOR_6M
            {9,15,6,21,14,20,12,5,24,16,1,4,13|POS_STEP,7,25,17,3,10,0,18,23,11,8,2,19,22|POS_STEP,},


            //"NZJHGRCXMYSWbOUFAIVLPEKQDt", ROTOR_7M
            {13,25,9,7,6,17,2,23,12,24,18,22,1|POS_STEP,14,20,5,0,8,21,11,15,4,10,16,3,19|POS_STEP,},


            //"FKQHTLXOCBJSpDZRAMEWNIUYGv", ROTOR_8M
            {5,10,16,7,19,11,23,14,2,1,9,18,15|POS_STEP,3,25,17,0,12,4,22,13,8,20,24,6,21|POS_STEP,},


            //"LEYJVCNIXWPBQMDRTAKZGFUHOS", ROTOR_BETA
            {11,4,24,9,21,2,13,8,23,22,15,1,16,12,3,17,19,0,10,25,6,5,20,7,14,18,},


            //"FSOKANUERHMBTIYCWLQPZXVGJD", ROTOR_GAMMA
            {5,18,14,10,0,13,20,4,17,7,12,1,19,8,24,2,22,11,16,15,25,23,21,6,9,3,},


            //"ENKQAUYWJICOPBLMDXZVFTHRGS", ROTOR_REFL4B
            {4,13,10,16,0,20,24,22,9,8,2,14,15,1,11,12,3,23,25,21,5,19,7,17,6,18,},


            //"RDOBJNTKVEHMLFCWZAXGYIPSUQ", ROTOR_REFL4C
            {17,3,14,1,9,13,19,10,21,4,7,12,11,5,2,22,25,0,23,6,24,8,15,18,20,16,},
        };


        private rotorwiringnames reflector;
        public string Reflector
        {
            get
            {
                if (reflector == rotorwiringnames.ROTOR_REFL4B)
                    return "B";
                else return "C";
            }
            set
            {
                switch (value)
                {
                    case "B":
                        reflector = rotorwiringnames.ROTOR_REFL4B;
                        break;
                    case "C":
                        reflector = rotorwiringnames.ROTOR_REFL4C;
                        break;
                    default:
                        throw new System.ArgumentException("Invalid reflector");
                }
            }
        }


        private rotorwiringnames[] rotors = new rotorwiringnames[ROTORS];
        public string Rotors
        {
            get
            {
                string s1;


                //thin rotor 0
                if (rotors[0] == rotorwiringnames.ROTOR_BETA)
                    s1 = "B";
                else s1 = "G";


                //remaining rotors
                for (int i1 = 1; i1 < ROTORS; i1++)
                    s1 += (char)(rotors[i1] + '1');


                return s1;
            }
            set
            {
                rotorwiringnames[] rotors2 = new rotorwiringnames[ROTORS];


                if (value == null || value.Length != ROTORS)
                    throw new System.ArgumentException("Invalid rotors");


                //thin rotor 0
                if (value[0] == 'B')
                    rotors2[0] = rotorwiringnames.ROTOR_BETA;
                else
                if (value[0] == 'G')
                    rotors2[0] = rotorwiringnames.ROTOR_GAMMA;
                else throw new System.ArgumentException("Invalid rotors");


                //remaining rotors
                for (int i1 = 1; i1 < ROTORS; i1++)
                    if (value[i1] >= '1' && value[i1] <= '8')
                        rotors2[i1] = (rotorwiringnames)(value[i1] - '1');
                    else throw new System.ArgumentException("Invalid rotors");


                //assign
                rotors = rotors2;
            }
        }


        private int[] rings = new int[ROTORS];
        public string Rings
        {
            get
            {
                string s1 = "";
                int i1;


                //rotors
                for (i1 = 0; i1 < ROTORS; i1++)
                    s1 += (char)(rings[i1] + 'A');


                return s1;
            }
            set
            {
                int[] rings2 = new int[ROTORS];


                if (value == null || value.Length != ROTORS)
                    throw new System.ArgumentException("Invalid rings");


                //rotors
                for (int i1 = 0; i1 < ROTORS; i1++)
                    if (value[i1] >= 'A' && value[i1] <= 'Z')
                        rings2[i1] = value[i1] - 'A';
                    else throw new System.ArgumentException("Invalid rings");


                //assign
                rings = rings2;
            }
        }


        private int[] indicators = new int[ROTORS];
        public string Indicators
        {
            get
            {
                string s1 = "";
                int i1;


                //rotors
                for (i1 = 0; i1 < ROTORS; i1++)
                    s1 += (char)(indicators[i1] + 'A');


                return s1;
            }
            set
            {
                int[] indicators2 = new int[ROTORS];


                if (value == null || value.Length != ROTORS)
                    throw new System.ArgumentException("Invalid indicators");


                //rotors
                for (int i1 = 0; i1 < ROTORS; i1++)
                    if (value[i1] >= 'A' && value[i1] <= 'Z')
                        indicators2[i1] = value[i1] - 'A';
                    else throw new System.ArgumentException("Invalid indicators");


                //assign
                indicators = indicators2;
            }
        }


        private int[,] plugboard = new int[POSITIONS / 2, 2];
        private int plugboarditems;
        public string Plugboard
        {
            get
            {
                string s1 = "";
                int i1;


                //rotors
                for (i1 = 0; i1 < plugboarditems; i1++)
                {
                    if (s1.Length > 0)
                        s1 += ' ';


                    for (int i2 = 0; i2 < 2; i2++)
                        s1 += (char)(plugboard[i1, i2] + 'A');


                }


                return s1;
            }
            set
            {
                int[,] plugboard2 = new int[POSITIONS / 2, 2];
                int plugboarditems2;
                bool[] used = new bool[POSITIONS];


                if (value == null)
                    throw new System.ArgumentException("Invalid plugboard");


                //convert to uppercase and remove all spaces
                value = value.ToUpper().Replace(" ", "");


                //does it have an even number of characters
                if (value.Length % 2 == 1)
                    throw new System.ArgumentException("Invalid plugboard");


                plugboarditems2 = value.Length / 2;
                for (int i1 = 0; i1 < plugboarditems2; i1++)
                    if (value[i1 * 2] >= 'A' && value[i1 * 2] <= 'Z' && !used[value[i1 * 2] - 'A'] &&
                        value[i1 * 2 + 1] >= 'A' && value[i1 * 2 + 1] <= 'Z' && !used[value[i1 * 2 + 1] - 'A'] &&
                        value[i1 * 2] != value[i1 * 2 + 1])
                    {
                        plugboard2[i1, 0] = value[i1 * 2] - 'A';
                        used[value[i1 * 2] - 'A'] = true;


                        plugboard2[i1, 1] = value[i1 * 2 + 1] - 'A';
                        used[value[i1 * 2 + 1] - 'A'] = true;
                    }
                    else throw new System.ArgumentException("Invalid plugboard");




                //assign
                plugboard = plugboard2;
                plugboarditems = plugboarditems2;
            }
        }


        public Enigma()
        {
            InitializeMachine();
        }


        public void InitializeMachine()
        {
            Reflector = "B";
            Rotors = "B123";
            Rings = "AAAA";
            Indicators = "AAAA";
            Plugboard = "";
        }


        public void StepRotors()
        {
            int[] advance = new int[ROTORS] { 0, 0, 0, 1 };


            if ((rotorwiring[(int)rotors[3], indicators[3]] & POS_STEP) == POS_STEP)
                advance[2] = 1;


            if ((rotorwiring[(int)rotors[2], indicators[2]] & POS_STEP) == POS_STEP)
            {
                advance[1] = 1;
                advance[2] = 1;
            }


            for (int i1 = 0; i1 < ROTORS; i1++)
                if (advance[i1] == 1)
                {
                    indicators[i1]++;
                    if (indicators[i1] >= POSITIONS)
                        indicators[i1] = 0;
                }
        }


        private int ForwardThroughRotor(rotorwiringnames ARotor, int AIndicator, int ARing, int AKey)
        {
            return (((rotorwiring[(int)ARotor, (AIndicator + (POSITIONS - ARing) + AKey) % POSITIONS] & POS_ONLY) + (POSITIONS - AIndicator) + ARing) % POSITIONS);
        }


        private int ReverseThroughRotor(rotorwiringnames ARotor, int AIndicator, int ARing, int AKey)
        {
            for (int i1 = 0; i1 < POSITIONS; i1++)
                if (AKey == ForwardThroughRotor(ARotor, AIndicator, ARing, i1))
                    return i1;
            throw new System.ArgumentException("Invalid rotorwiring");
        }


        public int PlugboardTraverse(int AKey)
        {
            for (int i1 = 0; i1 < plugboarditems; i1++)
                if (AKey == plugboard[i1, 0])
                    return plugboard[i1, 1];
                else
                if (AKey == plugboard[i1, 1])
                    return plugboard[i1, 0];
            return AKey;
        }


        public int Cipher(int AKey)
        {
            //step the rotors properly
            StepRotors();


            //go through plugboard
            AKey = PlugboardTraverse(AKey);


            //forward through rotors
            for (int i1 = ROTORS - 1; i1 >= 0; i1--)
                AKey = ForwardThroughRotor(rotors[i1], indicators[i1], rings[i1], AKey);


            //forward through reflector
            AKey = ForwardThroughRotor(reflector, 0, 0, AKey);


            //reverse through rotors
            for (int i1 = 0; i1 < ROTORS; i1++)
                AKey = ReverseThroughRotor(rotors[i1], indicators[i1], rings[i1], AKey);


            //go through plugboard
            AKey = PlugboardTraverse(AKey);


            return AKey;
        }


        public string Cipher(string AString)
        {
            string s1, s2;


            s1 = AString.ToUpper();
            s2 = "";


            foreach (char c in s1)
                if (c >= 'A' && c <= 'Z')
                    s2 = s2 + (char)(Cipher(c - 'A') + 'A');


            return s2;
        }
    }
}

Example output:

REFL=B
ROTR=B123
RING=AAAA
PLUG=BE ZY
INDC=AAAA


IN:AAAAA
OUT:EDYGO


REFL=B
ROTR=B123
RING=AAAA
PLUG=BE ZY
INDC=AAAF
Press any key to continue . . .
 
Back
Top Bottom