0

My project is breaking a Vignere cipher. However, I've gotten to this last part and now I'm stuck. I don't know if I'm misunderstanding the math or the logic of the program I'm writing, but basically I should be getting different calcDistribution() values for each letter at each position of the key. As it stands, this program returns only 16 unique values grouped together by key position. Ultimately the program should be able to pick the highest value calcDistribution() letter at that key position.

Here is the portion of my code I'm sure is the source of the problem:

//First, we need to pick a character to XOR against the cipherText. reuse char ci, string byte
char kg;
string keyBreakGuess = "";
string ranOuttaNames1 = "";
string ranOuttaNames2 = "";
float charDistribution[128-65][MAXKEY];
for(int d = 0; d < keyGuess; d++){ //This loop will search each spot up to the length of the key
    for(ci = 65; ci < 123; ci++){ //This loop will look at every possible key character
        cipherText.seekg(0, ios::beg);
        for(int e = 0; e < 500 && !cipherText.eof(); e++){  //This loop will handle the sampling
            cipherText.seekg((LENGTH * keyGuess * e) + (LENGTH * d), ios::beg); //f(x) = 8*(c)*(x) + 8*(b)
            if(cipherText.eof())
                break;
            for(int f = 0; f < LENGTH && !cipherText.eof(); f++){
                cipherText >> kg;
                byte += kg;
            }
            ranOuttaNames2 = ci;
            ranOuttaNames1 = string2Binary(ranOuttaNames2);
            ranOuttaNames2 = "";
            for(int u = 0; u < LENGTH; u++){
                if(byte[u] == ranOuttaNames1[u])
                    ranOuttaNames2 += '0';
                else
                    ranOuttaNames2 += '1';
            }
            kg = binary2Char(ranOuttaNames2);
            if((int)kg >= 32 && (int)kg < 128)
                ascii[(int)kg]++;
            byte = "";
            ranOuttaNames1 = "";
        }
        //This is where we will calcDist for each char and pick the max character for that piece of the key
        charDistribution[(int)ci-65][d] = calcDistribution(ascii, ASCIIBYTELENGTH);
        cout << ci << " " << (d+1) << ": " << charDistribution[(int)ci-65][d] << endl;
        for(int r = 0; r < ASCIIBYTELENGTH; r++){
            ascii[r] = 0;
        }
    }
}

maxD = 0;
for(int s = 0; s < keyGuess; s++){
    for(int q = 65; q < 128; q++){
        if(maxD < charDistribution[q-65][s]){
            maxD = charDistribution[q-65][s];
            kg = q;
        }
    }
    keyBreakGuess += kg;
}

cout << "My guess for the full key: " << keyBreakGuess << endl; //This should have the full key

Here is the calcDistribution function:

//This function will calculate the distribution of characters of an array
double calcDistribution(int arr[], int size)
{
    double p = 0.000;
    double sum = 0;
    //calculate sum of all indexes
    for(int t = 0; t < size; t++){
        sum += arr[t];
    }
    //divide each point point in the index by the sum of all indexes
    for(int c = 0; c < size; c++){
        try{
            p += pow((arr[c] / sum), 2);
        } catch (int e) {
            cerr << "Sum is 0, error occurred.";
            exit(1);
        }
    }

    return p;
}

Any pointers in the right direction would be much appreciated.

  • Warning: [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – user4581301 Feb 17 '21 at 03:08
  • When you know what you should get for your inputs, step through the program with a debugger and keep an eye out for where the program violates your expectations. Save you a ton of time. – user4581301 Feb 17 '21 at 03:10
  • Warning: [Catching exception: divide by zero](https://stackoverflow.com/questions/6121623/catching-exception-divide-by-zero) – user4581301 Feb 17 '21 at 03:18
  • Note: In `for(ci = 65; ci < 123; ci++)` prefer to use the characters. They're usually portable and easier to read. `for(ci = 'A'; ci < '{'; ci++)` But in this case `for(ci = 'A'; ci <= 'z'; ci++)` is probably even easier to read. Note that in ascii there are a few punctuation characters in there. In the rare case where the encoding is not ascii, all bets are off. For all you know `'z'` might come before `'A'` – user4581301 Feb 17 '21 at 03:23

1 Answers1

0

I solved this problem by adding a case to break if a character wasn't printable or a number or letter. This kept values from repeating because it wouldn't even calculate a value with special characters. While this probably wouldn't hold true for every possible document you would want to encrypt with a Vignere cipher, it did work for the document I was given for this project.