我的 C++ 语言蛮力算法问题

Issue with my Brute Force Algorithm in C++ Language

我遇到了一个问题,我要创建一个程序,该程序具有使用 ASCII 生成随机密码的功能 table( 使用 srand 生成 0 到 256 之间的随机数,然后将它们转换为字符.), 另一个显示生成密码的函数。然后另一个函数使用暴力方法破解生成的密码。生成密码的函数工作正常,但我遇到的问题是破解密码的函数。

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

void Generate_Pass(char pass[5])
{
    int seed = time(NULL);
    srand(seed);
    for(int i = 0; i < 5; i++){
        pass[i] = rand()%256;
    }
}

void Display_Pass(char pass[5])
{
    for(int i = 0; i < 5; i++){
        cout << pass[i] << " ";
    }
}

void Cracked(char cracked[5], char pass[5])
{
    do
    {
        for(int a = 0; a < 5; a++){
            int b = rand()%256;
            cracked[a] = char(b);
        }
    }while(cracked[0] != pass[0]);
    do
    {
        for(int a = 0; a < 5; a++){
            int b = rand()%256;
            cracked[a] = char(b);
        }
    }while(cracked[1] != pass[1]);
    do
    {
        for(int a = 0; a < 5; a++){
            int b = rand()%256;
            cracked[a] = char(b);
        }
    }while(cracked[2] != pass[2]);
    do
    {
        for(int a = 0; a < 5; a++){
            int b = rand()%256;
            cracked[a] = char(b);
        }
     }while(cracked[3] != pass[3]);
    do
    {
        for(int a = 0; a < 5; a++){
            int b = rand()%256;
            cracked[a] = char(b);
        }
    }while(cracked[4] != pass[4]);
}

void Display_Cracked(char cracked[5])
{
    for(int i = 0; i < 5; i++){
        cout <<  cracked[i] << " ";
    }
}

int main()
{
    char pass[5];
    Generate_Pass(pass);
    cout << "The Password is: ";
    Display_Pass(pass);
    cout << "\n";
    char cracked[5];
    Cracked(cracked, pass);
    cout << "The cracked password is: ";
    Display_Cracked(cracked);
}

那是我处理过的代码,但每当我 运行 时,蛮力函数就无法正常工作。

首先,在您的 Cracked 方法中,您仅以一个索引为条件遍历所有五个索引。你这样做五次。平均需要 256 次尝试才能匹配正确的字符。这导致生成和分配大约 5*5*256=6400 个整数,这比您需要的工作量要多。

您的代码的问题是您在每个 do while 循环中分配给所有五个索引。然后,您在上一个循环中找出的任何正确字符都将在下一个循环中被随机数据覆盖,因此只有最后一个字符是正确的。下面是修复这些问题的调整实施。

void Cracked(char cracked[5], char pass[5]) {
  for (int a = 0; a < 5; a++) {
    do {
      int b = rand() % 256;
      cracked[a] = char(b);
    } while(cracked[a] != pass[a]);
  }
}

由于 for 循环现在在外面,它会尝试随机的东西,直到找出一个字符,然后在不触及任何其他字符的情况下继续下一个字符。

您还会注意到,使用 for 循环会产生更少的代码,但大部分是相同的。通常,如果您发现自己在复制粘贴代码,这意味着您应该使用循环或函数或其他一些构造来避免额外的代码或让编译器为您生成它。这使您的代码更易于维护。例如,如果您想替换每个 do while 循环中使用的 rand 函数,您只需替换一次而不是五次。

此外,在这种情况下,最好分别尝试所有可能的值而不是随机值(例如使用 for 循环)。我会让你弄清楚那部分。

一个Brute Force解决方案是:

Systematically enumerating all possible candidates for the solution and checking whether each candidate satisfies the problem's statement

这意味着您需要生成给定长度的所有可能组合。 (你永远不能保证你已经使用 rand 做到了这一点。)由于 你不应该使用幻数所以我们称这个长度为:

#define LENGTH 5

从那里你可以做一个简单的嵌套 while-loop:

string Cracked(const char* pass) {
    string result('[=11=]', LENGTH);

    while(!equal(cbegin(result), cend(result), pass)) {
        if(result.back() < numeric_limits<unsigned char>::max()) {
            ++result.back();
        } else {
            for(auto it = rbegin(result); it != rend(result); *it++ = '[=11=]') {
                if(*it < numeric_limits<unsigned char>::max()) {
                    ++(*it);
                    break;
                }
            }
        }
    }
    return result;
}