/// <summary>
        /// Decrypt the given ciphertext using the pre-set list of decryption keys
        /// Assumes the list of decryption keys has been populated already
        /// </summary>
        static string DecryptCipherText(string cipherAsHex)
        {
            if (DecryptionKeys.Count == 0)
            {
                Console.WriteLine("ERROR: We don't seem to have a list of encryption keys.");
                return("ERROR");
            }

            string decryptedCipher = string.Empty;

            byte[] cipherAsBytes = StringToByteArray(cipherAsHex);

            // Iterate over the give cipher text and decrypt
            for (int i = 0; i < cipherAsBytes.Length; i++)
            {
                // Find the decrytion key for this position
                DecryptionKey key = FindDecryptionKey(i);

                if (key == null)
                {
                    // We don't have a key for this position somehow - output ? instead
                    decryptedCipher += "?";
                    continue;
                }

                int xorResult = cipherAsBytes[i] ^ key.Key;

                // Convert to ASCII character
                char decryptedChar = Convert.ToChar(xorResult);

                decryptedCipher += decryptedChar;
            }

            return(decryptedCipher);
        }
        static List <DecryptionKey> DecryptionKeys;      // List of decryption keys per position (built up along the way)

        static void Main(string[] args)
        {
            // Read the given ciphertexts from the XML file where I store them
            CipherTexts    = ReadCipherTexts();
            DecryptionKeys = new List <DecryptionKey>();

            Console.WriteLine("Read {0} ciphertexts from XML.", CipherTexts.Count);

            int currentCipherIndex = 0;

            // Iterating over Ciphers as Hex Strings
            while (currentCipherIndex < CipherTexts.Count)
            {
                Console.WriteLine("Current Cipher Index: " + currentCipherIndex);

                byte[] currentCipherAsBytes = StringToByteArray(CipherTexts[currentCipherIndex]);

                int currentByteIndex = 0;

                // Iterating over Bytes in the current Cipher
                while (currentByteIndex < currentCipherAsBytes.Length)
                {
                    Console.WriteLine("Checking Index: " + currentByteIndex);

                    // Get the current byte
                    byte currentByteValue = (byte)currentCipherAsBytes.GetValue(currentByteIndex);

                    // XOR this byte with the corresponding byte in each ciphertext (until we find a potential key)
                    for (int i = currentCipherIndex + 1; i < CipherTexts.Count; i++)
                    {
                        byte[] cipherAsBytes = StringToByteArray(CipherTexts[i]);

                        byte byteToXorAgainst;

                        try
                        {
                            byteToXorAgainst = cipherAsBytes[currentByteIndex];
                        }
                        catch
                        {
                            // No correspdonging byte at this location in this cipher (e.g. cipher could be shorter than the current one)
                            continue;
                        }

                        // XOR
                        int xor = currentByteValue ^ byteToXorAgainst;

                        // Check if we got an uppercase ASCII character
                        if (IsUpperCaseAscii(xor))
                        {
                            Console.WriteLine("XOR of current check (" + xor + ") is an uppercase ASCII character, value is: " + Convert.ToChar(xor));

                            // This means that one of the plain text characters is a space and one is the lowercase ASCII equivalent of this character

                            // We need to XOR each potential key with an ASCII space
                            int potentialKey1 = currentByteValue ^ 32;
                            int potentialKey2 = byteToXorAgainst ^ 32;

                            // These are our pontetial keys
                            Console.WriteLine("Potential Key 1 - " + potentialKey1);
                            Console.WriteLine("Potential Key 2 - " + potentialKey2);

                            // Check one of these keys is valid - if one isn't we'll assume the other is
                            Console.WriteLine("Checking Potential Key - " + potentialKey1);

                            if (CheckPotentialKey(potentialKey1, currentByteIndex))
                            {
                                Console.WriteLine("Key is valid - " + potentialKey1);

                                DecryptionKey key = new DecryptionKey();
                                key.Key      = potentialKey1;
                                key.Position = currentByteIndex;
                                DecryptionKeys.Add(key);
                            }
                            else
                            {
                                Console.WriteLine("Key '" + potentialKey1 + "' not valid, assuming key '" + potentialKey2 + "' is valid");

                                DecryptionKey key = new DecryptionKey();
                                key.Key      = potentialKey2;
                                key.Position = currentByteIndex;
                                DecryptionKeys.Add(key);
                            }

                            // Break out of checking further bytes at this position as we've found a valid key
                            break;
                        }
                    }

                    currentByteIndex++;
                }

                currentCipherIndex++;
            }

            // Decrypt the Ciphertexts
            Console.WriteLine("Now to decrypt the ciphertexts...");

            for (int i = 0; i < CipherTexts.Count; i++)
            {
                string decryptedCipher = DecryptCipherText(CipherTexts[i]);
                Console.WriteLine("Decrypted Ciphertext at Position '" + i + "' - " + decryptedCipher);
            }
        }