【问题标题】:Scanning a cipher text document, guessing the key, and calculating distribution扫描密文文档,猜测密钥,计算分布
【发布时间】:2021-05-19 22:20:52
【问题描述】:

我的项目正在破解 Vignere 密码。但是,我已经到了最后一部分,现在我被卡住了。我不知道我是否误解了我正在编写的程序的数学或逻辑,但基本上我应该在键的每个位置为每个字母获得不同的 calcDistribution() 值。就目前而言,该程序仅返回按关键位置组合在一起的 16 个唯一值。最终,程序应该能够在该关键位置选择最高值的 calcDistribution() 字母。

这是我确定是问题根源的部分代码:

//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

这是 calcDistribution 函数:

//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;
}

任何正确方向的指针将不胜感激。

【问题讨论】:

  • 当你知道你的输入应该得到什么时,使用调试器逐步完成程序,并留意程序在哪里违反了你的期望。为您节省大量时间。
  • 注意:在for(ci = 65; ci &lt; 123; ci++) 中更喜欢使用字符。它们通常是便携的并且更容易阅读。 for(ci = 'A'; ci &lt; '{'; ci++) 但在这种情况下,for(ci = 'A'; ci &lt;= 'z'; ci++) 可能更容易阅读。请注意,在 ascii 中有一些标点符号。在编码不是 ascii 的极少数情况下,所有的赌注都被取消了。据您所知,'z' 可能会在 'A' 之前出现

标签: c++ math cryptography


【解决方案1】:

如果字符不可打印或数字或字母,我通过添加一个案例来解决这个问题。这可以防止值重复,因为它甚至不会计算带有特殊字符的值。虽然这可能不适用于您想要使用 Vignere 密码加密的每个可能的文档,但它确实适用于我为此项目提供的文档。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-04
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    相关资源
    最近更新 更多