Search code examples
javaencryptionkeyshift

Method to decrypt a shift cipher without knowing the key but knowing one of the words that the plaintext will contain - Java


I am currently trying to write an app that is supposed to read in a ciphertext from a file and decrypt it using shift cipher without knowing the key, but knowing that one of the words in the String is "DONE". This is the method I have so far, it iterates through all 25 keys and I am trying to check if the String.contains("DONE"), but for whatever reason it's like the method doesn't even acknowledge the existence of that particular if statement and just progresses through all 25 keys. I realize the answer might be obvious, but I just can't see it... Here's my code:

public String decryptUnknownKey()
    {
        char[] ciphertext = this.ciphertext.toUpperCase().toCharArray();
        char c;
        char[] plaintext = new char[ciphertext.length];
        String test = "";
        String search = "DONE";
        boolean keyFound = false;

        while(!keyFound)
        {
            for (int key = 1; key < 25; key++)
            {
                for (int i = 0; i < ciphertext.length; i++)
                {
                    if(ciphertext[i] >= 'A' && ciphertext[i] <= 'Z')
                    {
                        c = (char) (Math.floorMod(ciphertext[i] - 65 - key, 26) + 65);
                        plaintext[i] = c;
                    }
                    else if(Character.isWhitespace(ciphertext[i]) == true)
                    {
                        plaintext[i] = 32;
                    }
                }
                test = String.valueOf(plaintext);
                if (test.contains(search))
                {
                    keyFound = true;
                }
            }
        }
        return test;
    }

Solution

  • you are nesting three loops

    a) while
    b) -- for
    c)    -- for
    

    Your outer for loops b) keeps looping over all the keys, even if it sets keyFound = true. This is, because you use the keyFound as an exit condition for a) and not for b). So b) will continue until it tried all keys, before a) is reavaluated. Beware, if NO key fits, the while loop will never terminate.

    Also nesting loops is usually considered a code smell. You might want to just remove the outer while loop completely and stick only with b) and c) as a first step. To terminate the outer for loop, use a break statement instead of a boolean flag. Here's some sample https://www.tutorialspoint.com/java/java_break_statement.htm