-2

I'm creating a basic caesar cipher encryption/decryption. I'm having an issue where a random "u" is appearing instead of a space.. Any not sure how to correct this, any advice would be very much appreciated.

// Decryption Method //
static void decryption() {
    Console.ForegroundColor = ConsoleColor.DarkBlue;
    Console.WriteLine("\n*********************************** Decryption *********************************");
    Console.ResetColor();
    //pulls getPath from varables class
    string path = globalVars.getPath();
    string fileContent = "";
    string encrypted_text = System.IO.File.ReadAllText(path); //String variable that contains the text from a file. To get the text, the method in a class SystemIO is ran to read the text. It expects a parameter, which is a file directory.
    string decoded_text = " ";
    int shift = 0;
    char character = '0';
    encrypted_text = encrypted_text.ToUpper();

    char[] alphabet = new char[26] {
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
    };

    Console.WriteLine("The encrypted text is \n{0}", encrypted_text); //Display the encrypted text

    for (int i = 0; i < alphabet.Length; i++) //Start a loop which will display 25 different candidates of decipher
    {
        decoded_text = "";
        foreach(char c in encrypted_text) {
            character = c;

            if (character == '\'' || character == ' ') continue;

            shift = Array.IndexOf(alphabet, character) - i; //Define a shift which is the index of a character in an alphabet array, take away the itteration of this loop. Store the result in a variable
            if (shift <= 0) shift = shift + 26;

            if (shift >= 26) shift = shift - 26;


            decoded_text += alphabet[shift];
        }
        Console.WriteLine("\n\nShift {0} \n\n {1}", i + 1, decoded_text);
        fileContent += "Shift " + (i + 1).ToString() + "\r\n" + decoded_text + "\r\n";
    }
        // Save Decrypted Output to .TXT file - allows user to choose save path within filesystem.
    string filename;
    string savePath;

    Console.ForegroundColor = ConsoleColor.DarkBlue;
    Console.WriteLine("\nWhat do you want to name your file??");
    Console.ResetColor();
    filename = Console.ReadLine();

    Console.ForegroundColor = ConsoleColor.DarkBlue;
    Console.WriteLine("Where would you like to save your file??");
    Console.ResetColor();
    savePath = Console.ReadLine();

    File.WriteAllText(savePath + filename + ".txt", fileContent);
    Console.ForegroundColor = ConsoleColor.DarkBlue;
    Console.WriteLine("File Saved");
    Console.WriteLine(Console.Read());
}

Please see below for images of both input and output text

Input Text Output text

Grant Winney
  • 65,241
  • 13
  • 115
  • 165
  • 2
    Have you tried to debug it? – Sergii Zhevzhyk Dec 06 '15 at 23:34
  • 1
    Sample input and output text would help. – Mike Nakis Dec 06 '15 at 23:47
  • 1
    Can you highlight the incorrect characters in the screenshots? Or, if possible, provide a shorter example? – vesan Dec 07 '15 at 00:24
  • Sure here's an example: THEINCREDIBLELEGACYOUFTHEMATHEMATICALGENIUUSGEORGEBOOLEWILLBEEUXPLOREDINAFREEPUBLICUTALKINHISHOMECITYOFLUINCOLNONTHEBICENTENAURYOFHISBIRTHSTOPBOOLUEWASBORNONTHESECONDOUFNOVEMBER – Vanessa Stratfold Dec 07 '15 at 00:26
  • By the way, this near exact question has been re-asked here http://stackoverflow.com/questions/34127381/console-output-displaying-a-u-every-20-characters-c-sharp 6 hours later :( –  Dec 07 '15 at 06:20
  • @Micky: and [here](https://stackoverflow.com/q/34124857), by the same person who posted this question. This question seems to really like to reproduce. :) – Peter Duniho Dec 07 '15 at 06:51
  • @PeterDuniho lol. _Viral_ questions ;) –  Dec 07 '15 at 06:53

3 Answers3

2

Your bug originates from the fact that Array.IndexOf returns -1 (ie, equivalent to z) if the character is not present in the array, so giving a shift of -1 - i. In particular, the new line characters every 20 characters are causing problems.

I would suggest your check of

if (character == '\'' || character == ' ')
    continue;

be replaced with a check

if (!alphabet.Contains(character))
{
    decoded_text += character;
    continue;
}

Which is much more robust, and in particular works for characters such as \n, or \r followed by \n (\r\n is a line break on windows). Adding the character to the output is optional, but maybe helpful.

David E
  • 1,384
  • 9
  • 14
  • It may also be worth looking into the remainder operator: `%` for your shifting. In particular, you can do: `shift = (shift + 26) % 26;`. But that's unrelated to your bug, just a slight neatening. – David E Dec 07 '15 at 00:25
1

Your problem is in the new line characters, which this line:

if (character == '\'' || character == ' ') continue;

does not check.

In that case, Array.IndexOf will return -1. Since your text is correctly decrypted when i == 5 (i.e. "Shift 6"), this will, for unknown characters, give you alphabet[20], which is U. The lines in your input file are 20 characters long and, indeed, the first wrong U appears after 20 characters in the output as well: THEINCREDIBLELEGACYOUFTHE...

You should instead check if Array.IndexOf(...) >= 0.

vesan
  • 3,289
  • 22
  • 35
0

I don't have a direct answer to your question, suffice to say that it is likely something to do with the way you shift bytes. I do, however, want to share a byte cipher that I found some time ago on the internet, which does exactly what you're trying to do, but in very few lines of code: Original Source Here

Despite the biased downvotes, the snippet of code is actually very good, and works well for simple obfuscation tactics. Here is the code just in case the link were to die:

public static class SimpleByteCipher
    {

        public static byte[] EncryptStringToByteArray( string data , string password , uint seed)
        {
            byte[] bytes = Encoding.ASCII.GetBytes( data );
            byte[] passwordBytes = Encoding.ASCII.GetBytes( password );
            int passwordShiftIndex = 0;
            for( int i = 0; i < bytes.Length; i++ )
            {
                bytes[ i ] = ( byte )( bytes[ i ] + passwordBytes[ passwordShiftIndex ] + seed );
                passwordShiftIndex = ( passwordShiftIndex + 1 ) % passwordBytes.Length;
            }
            return bytes;
        }

        public static string DecryptByteArrayToString( byte[] data , string password , uint seed)
        {
            byte[] bytes = data;
            byte[] passwordBytes = Encoding.ASCII.GetBytes( password );
            int passwordShiftIndex = 0;
            for( int i = 0; i < bytes.Length; i++ )
            {
                bytes[ i ] = ( byte )( bytes[ i ] - passwordBytes[ passwordShiftIndex ] - seed );
                passwordShiftIndex = ( passwordShiftIndex + 1 ) % passwordBytes.Length;
            }
            return Encoding.ASCII.GetString( bytes );
        }
    }

Again, I know this is not a direct answer, but perhaps you can learn something from the way that user did it.

Community
  • 1
  • 1