Search code examples
c++encryptioncryptographybrute-forcecaesar-cipher

Caesar Cipher bruteforce


This is my class exercise we have to brute force the follow "hdvb wr euhdn" and find the key that works, but my code breaks it (I think correctly) but two different keys produce the same outcome. Is this normal or am I doing it wrong?

Key 2 and 11 work, and a few others that don't work still repeat the same characters. We just covered basic Caesar shift ciphers and I figured this approach was the best brute force . enter image description here

#include<iostream>
#include<String>

using std::string;
using std::endl;

void bruteForce(string x);

void bruteForce(string x)
{

    int key = 0;

    int length = (int)x.length();

    for (int i = 0; i < 25; i++)
    {
        key++;
        std::cout << "The key is  " << key << endl;
        std::cout << endl;
        for (int j = 0; j < length; j++)
        {

            if (x[j] == ' ')
            {
                x[j] = ' ';
                std::cout << x[j];
                j++;
            }
            x[j] = tolower(x[j]);
            x[j] -= 97;
            x[j] -= key;
            if (x[j] < 0)
            {
                x[j] += 26;

            }
            x[j] += 97;

            std::cout << x[j];
        }

        std:: cout << endl;

    }

}

Solution

  • Each loop is modifying the input as mentioned by Alexander O'Mara - refactor to separate the key change from the test.

    Declare a function for the testing (separate to brute-force)

    void Test(std::string x, int key); 
    

    Call it from bruteForce.

    void bruteForce(string x)
    {
    
        int key = 0;
    
        for (int i = 0; i < 25; i++)
        {
            key++;
            Test( x, key );
        }
    }
    

    Implementation

    void Test(std::string x, int key)
    {
        int length = (int)x.length();
        std::cout << "The key is  " << key << endl;
        std::cout << endl;
        for (int j = 0; j < length; j++)
        {
            if (x[j] == ' ')
            {
                x[j] = ' ';
                std::cout << x[j];
            }
            else {
                x[j] = tolower(x[j]);
                x[j] -= 97;
                x[j] -= key;
                if (x[j] < 0)
                {
                    x[j] += 26;
    
                }
                x[j] += 97;
            }
            std::cout << x[j];
        }
    
        std::cout << endl;
    
    
    
    }
    

    I slightly changed your skip for space, so that 2 spaces in a row, wouldn't confuse it.

    The code works because each call to Test is a new copy of the pristine string. Each successive key for a cesear cypher shifts by one character, so that should have alerted you to the re-use of the string.