C++实现密码破解时如何自动化嵌套循环支持任意长度密码
问题说明
编写暴力破解密码程序时,硬编码嵌套循环仅支持固定长度(当前为4位)的密码破解,若要支持更长密码需要反复复制粘贴循环、判断逻辑,代码冗余且维护成本高,需要实现无需硬编码嵌套层数、支持任意指定最大长度密码的破解逻辑。
原有硬编码实现如下:
#include <iostream> #include <string> #include <ctime> using namespace std; const char alphanum[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&* "; const string pw = "0000"; bool cracked = false; int tries = 0; const int pwLength = pw.length(); string crack(); string guess="0"; const int maxLen = 30; int main() { clock_t begin, end; double time; begin = clock(); string crackedPassword = crack(); end = clock(); time = double(end - begin) / (double)CLOCKS_PER_SEC; cout << "The password is: " << crackedPassword << " The program checked a total of " << tries << " possibilites and took " << time << " seconds to crack the password!"; return 0; } string crack() { int index = 0; int repeat = 0; while (!cracked) { for (int i = 0; i < 71; i++) { tries++; guess[index] = alphanum[i]; cout << "Trying: " << guess << endl; if (repeat > 0) { for (int i = 0; i < 71; i++) { tries++; guess.push_back(alphanum[i]); cout << "Trying: " << guess << endl; if (repeat > 1) { for (int i = 0; i < 71; i++) { tries++; guess.push_back(alphanum[i]); cout << "Trying: " << guess << endl; if (repeat > 2) { for (int i = 0; i < 71; i++) { tries++; guess.push_back(alphanum[i]); cout << "Trying: " << guess << endl; if (guess == pw) { cracked = true; break; } else { guess.pop_back(); } } } if (guess == pw) { cracked = true; break; } else { guess.pop_back(); } } } if (guess == pw) { cracked = true; break; } else { guess.pop_back(); } } } if (guess == pw) { cracked = true; break; } } repeat++; } return guess; }
实现思路
硬编码嵌套循环本质是固定深度的遍历,要支持可变深度,用递归回溯即可实现,不需要手动写多层循环:
- 按密码长度从小到大枚举(从1位到设定的最大长度),和原有逻辑一致
- 递归时维护当前拼接的猜测串,每次尝试往串末尾追加一个字符集中的字符
- 若当前串长度等于当前枚举的密码长度,就和目标密码做比对:匹配则直接返回结果,不匹配则回退最后一位字符,尝试下一个可选字符
- 全程不需要硬编码循环层数,修改最大长度参数即可支持对应长度的密码破解
另外原代码中写死的71是魔法数字,实际可以通过字符集数组自动计算长度,避免后续修改字符集时漏改数值导致bug。
修正后可运行代码
#include <iostream> #include <string> #include <ctime> using namespace std; const char alphanum[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&* "; const int charsetLen = sizeof(alphanum) - 1; // 自动计算字符集长度,去掉末尾结束符'\0' const string targetPw = "0000a"; // 可修改为任意长度的测试密码 bool cracked = false; int tries = 0; const int maxLen = 30; string result; // 递归回溯函数 void backtrack(string& currentGuess, int targetLen) { if (cracked) return; // 已经找到密码直接返回 // 长度达到当前目标长度,做比对 if (currentGuess.size() == targetLen) { tries++; // 调试时可打开打印,正式跑建议关闭,IO开销极高 // cout << "Trying: " << currentGuess << endl; if (currentGuess == targetPw) { cracked = true; result = currentGuess; } return; } // 遍历所有可选字符 for (int i = 0; i < charsetLen; i++) { if (cracked) return; currentGuess.push_back(alphanum[i]); backtrack(currentGuess, targetLen); currentGuess.pop_back(); // 回溯,撤销本次选择 } } string crack() { string guess; // 从小到大枚举密码长度 for (int len = 1; len <= maxLen; len++) { if (cracked) break; guess.clear(); backtrack(guess, len); } return result; } int main() { clock_t begin, end; double timeCost; begin = clock(); string crackedPassword = crack(); end = clock(); timeCost = double(end - begin) / (double)CLOCKS_PER_SEC; cout << "The password is: " << crackedPassword << " The program checked a total of " << tries << " possibilites and took " << timeCost << " seconds to crack the password!"; return 0; }
注意事项
- 暴力破解的时间复杂度随密码长度呈指数级增长:以当前71个字符的字符集计算,6位密码就有
71^6 ≈ 1.28*10^11种组合,普通单线程程序跑可能需要数天,更长的密码靠单线程暴力破解基本不现实。 - 当前递归实现的最大深度为maxLen,即使设为30层也完全不会触发栈溢出,无需额外优化;如果偏好非递归写法,也可以用“类数字进位”的迭代逻辑实现相同效果,性能基本一致。
- 每次尝试都打印猜测内容会产生极大的IO开销,严重拖慢运行速度,非调试场景建议移除打印逻辑。
内容的提问来源于stack exchange,提问作者Simply
相关产品推荐
相关产品推荐

