如何在找到密钥时终止凯撒密码暴力破解程序
问题
我写了一个能根据输入偏移量完成凯撒密码加解密的程序,核心功能已经实现,但暴力破解模块遇到了麻烦——没法找到通用的最优终止条件。目前只能针对已知密钥为17的测试用例写临时判断逻辑,想实现一个适用于所有输入的方案,让程序在破解出有效英文语句或正确密钥时自动终止。
以下是我的C++代码:
char decrypt(char letter, int key); int main(){ // Part 3 Brute-Force Attack std::string ciphertext; std::cout << "Enter in the ciphertext: "; std::getline(std::cin, ciphertext); std::cout << "\nBrute-Force Decryptions:" << std::endl; int i = 0; int keyCode = 0; std::string gang = ""; int alphaArray[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; // The algorithm has nested for each loops, the first one keeps track of the key initialized to 0 // and the second loop goes through the string given and converts it to the proper value based // on the shift key. The reason we want to find 't', 'h' or 'e' is because this signifies the // begginning of an actual English sentence, and most likely our cracked message. I was able to // determine this would begin the correct string we are looking for by bruteforcing the first // few letters using pencil and paper for(auto key : alphaArray){ std::cout << "\nkey = " << key << ":\t"; for(auto letter : ciphertext){ letter = decrypt(letter, i); gang += letter; } std::cout << gang << std::endl; if (tolower(ciphertext[0]) - key + 26 == 't' && tolower(ciphertext[1]) - key == 'h' && tolower(ciphertext[2]) - key == 'e'){ keyCode = key; break; } i++; gang = ""; } // Output results std::cout << "\nPart 3 KeyCode: " << keyCode << std::endl; std::cout << "\n\n"; return 0; } ////////////////////////////////////////////////////////////////////////////////////// // Function: Attempts to decrypt letter by shifting it up the alphabet 'key' times / // Params: Letter as a char and key as an int value / // Return: Letter shifted 'key' times / ////////////////////////////////////////////////////////////////////////////////////// char decrypt(char letter, int key){ int position = (letter - key - 'A') % 26; if(position < 0) position += 26; return (char)position + 'a'; }
程序运行输出:
Brute-Force Decryptions: key = 0: kyvtjyzwkttzgyvitzjtrcjftbefnetrjtkyvttrvjrittzgyviftrwkvitalczljttrvjriftnyftivglkvucptljvutkyvttzgyvitkftgrjjtdvjjrxvjtkftyzjtkiffgjtulizextyzjtdzczkripttrdgrzxejtzetxrlchtefkvtkyrktkyvttrvjrittzgyvitzjtvrjzcpttirtbvutsptkyvtsilkvgwfitvtrkkrtbh key = 1: jxusixyvjssyfxuhsyisqbiesademdsqisjxussquiqhssyfxuhesqvjuhszkbykissquiqhesmxeshufkjutboskiutsjxussyfxuhsjesfqiiscuiiqwuisjesxyisjheefistkhydwsxyiscybyjqhossqcfqywdisydswqkbgsdejusjxqjsjxussquiqhssyfxuhsyisuqiybosshqsautsrosjxusrhkjufvehsusqjjqsag key = 2: iwtrhwxuirrxewtgrxhrpahdrzcdlcrphriwtrrpthpgrrxewtgdrpuitgryjaxjhrrpthpgdrlwdrgtejitsanrjhtsriwtrrxewtgridrephhrbthhpvthridrwxhrigddehrsjgxcvrwxhrbxaxipgnrrpbepxvchrxcrvpjafrcditriwpiriwtrrpthpgrrxewtgrxhrtphxanrrgprztsrqnriwtrqgjiteudgrtrpiiprzf key = 3: hvsqgvwthqqwdvsfqwgqozgcqybckbqogqhvsqqosgofqqwdvsfcqothsfqxizwigqqosgofcqkvcqfsdihsrzmqigsrqhvsqqwdvsfqhcqdoggqasggousgqhcqvwgqhfccdgqrifwbuqvwgqawzwhofmqqoadowubgqwbquoizeqbchsqhvohqhvsqqosgofqqwdvsfqwgqsogwzmqqfoqysrqpmqhvsqpfihsdtcfqsqohhoqye key = 4: gurpfuvsgppvcurepvfpnyfbpxabjapnfpgurppnrfneppvcurebpnsgrepwhyvhfppnrfnebpjubperchgrqylphfrqpgurppvcurepgbpcnffpzrffntrfpgbpuvfpgebbcfpqhevatpuvfpzvyvgnelppnzcnvtafpvaptnhydpabgrpgungpgurppnrfneppvcurepvfprnfvylppenpxrqpolpgurpoehgrcsbeprpnggnpxd key = 5: ftqoeturfooubtqdoueomxeaowzaizomeoftqoomqemdooubtqdaomrfqdovgxugeoomqemdaoitaodqbgfqpxkogeqpoftqooubtqdofaobmeeoyqeemsqeofaotueofdaabeopgduzsotueoyuxufmdkoomybmuszeouzosmgxcozafqoftmfoftqoomqemdooubtqdoueoqmeuxkoodmowqponkoftqondgfqbradoqomffmowc key = 6: espndstqenntaspcntdnlwdznvyzhynldnespnnlpdlcnntaspcznlqepcnufwtfdnnlpdlcznhszncpafepowjnfdponespnntaspcneznalddnxpddlrpdneznstdneczzadnofctyrnstdnxtwtelcjnnlxaltrydntynrlfwbnyzepneslenespnnlpdlcnntaspcntdnpldtwjnnclnvponmjnespnmcfepaqzcnpnleelnvb key = 7: dromcrspdmmszrobmscmkvcymuxygxmkcmdrommkockbmmszrobymkpdobmtevsecmmkockbymgrymbozedonvimeconmdrommszrobmdymzkccmwocckqocmdymrscmdbyyzcmnebsxqmrscmwsvsdkbimmkwzksqxcmsxmqkevamxydomdrkdmdrommkockbmmszrobmscmokcsvimmbkmuonmlimdromlbedozpybmomkddkmua key = 8: cqnlbqrocllryqnalrbljubxltwxfwljblcqnlljnbjallryqnaxljocnalsdurdblljnbjaxlfqxlanydcnmuhldbnmlcqnllryqnalcxlyjbblvnbbjpnblcxlqrblcaxxyblmdarwplqrblvrurcjahlljvyjrpwblrwlpjduzlwxcnlcqjclcqnlljnbjallryqnalrblnjbruhllajltnmlkhlcqnlkadcnyoxalnljccjltz key = 9: bpmkapqnbkkqxpmzkqakitawksvwevkiakbpmkkimaizkkqxpmzwkinbmzkrctqcakkimaizwkepwkzmxcbmltgkcamlkbpmkkqxpmzkbwkxiaakumaaiomakbwkpqakbzwwxaklczqvokpqakuqtqbizgkkiuxiqovakqvkoictykvwbmkbpibkbpmkkimaizkkqxpmzkqakmiaqtgkkziksmlkjgkbpmkjzcbmxnwzkmkibbiksy key = 10: aoljzopmajjpwolyjpzjhszvjruvdujhzjaoljjhlzhyjjpwolyvjhmalyjqbspbzjjhlzhyvjdovjylwbalksfjbzlkjaoljjpwolyjavjwhzzjtlzzhnlzjavjopzjayvvwzjkbypunjopzjtpspahyfjjhtwhpnuzjpujnhbsxjuvaljaohajaoljjhlzhyjjpwolyjpzjlhzpsfjjyhjrlkjifjaoljiybalwmvyjljhaahjrx key = 11: znkiynolziiovnkxioyigryuiqtuctigyiznkiigkygxiiovnkxuiglzkxiparoayiigkygxuicnuixkvazkjreiaykjiznkiiovnkxizuivgyyiskyygmkyizuinoyizxuuvyijaxotminoyisorozgxeiigsvgomtyiotimgarwituzkizngziznkiigkygxiiovnkxioyikgyoreiixgiqkjiheiznkihxazkvluxikigzzgiqw key = 12: ymjhxmnkyhhnumjwhnxhfqxthpstbshfxhymjhhfjxfwhhnumjwthfkyjwhozqnzxhhfjxfwthbmthwjuzyjiqdhzxjihymjhhnumjwhythufxxhrjxxfljxhythmnxhywttuxhizwnslhmnxhrnqnyfwdhhfrufnlsxhnshlfzqvhstyjhymfyhymjhhfjxfwhhnumjwhnxhjfxnqdhhwfhpjihgdhymjhgwzyjuktwhjhfyyfhpv key = 13: xligwlmjxggmtlivgmwgepwsgorsargewgxliggeiwevggmtlivsgejxivgnypmywggeiwevsgalsgvityxihpcgywihgxliggmtlivgxsgtewwgqiwwekiwgxsglmwgxvsstwghyvmrkglmwgqmpmxevcggeqtemkrwgmrgkeypugrsxigxlexgxliggeiwevggmtlivgmwgiewmpcggvegoihgfcgxligfvyxitjsvgigexxegou key = 14: wkhfvkliwfflskhuflvfdovrfnqrzqfdvfwkhffdhvdufflskhurfdiwhufmxolxvffdhvdurfzkrfuhsxwhgobfxvhgfwkhfflskhufwrfsdvvfphvvdjhvfwrfklvfwurrsvfgxulqjfklvfplolwdubffdpsdljqvflqfjdxotfqrwhfwkdwfwkhffdhvdufflskhuflvfhdvlobffudfnhgfebfwkhfeuxwhsirufhfdwwdfnt key = 15: vjgeujkhveekrjgtekuecnuqempqypecuevjgeecgucteekrjgtqechvgtelwnkwueecguctqeyjqetgrwvgfnaewugfevjgeekrjgtevqercuueoguuciguevqejkuevtqqruefwtkpiejkueoknkvctaeecorckipuekpeicwnsepqvgevjcvevjgeecgucteekrjgtekuegcuknaeetcemgfedaevjgedtwvgrhqtegecvvcems key = 16: uifdtijguddjqifsdjtdbmtpdlopxodbtduifddbftbsddjqifspdbgufsdkvmjvtddbftbspdxipdsfqvufemzdvtfeduifddjqifsdupdqbttdnfttbhftdupdijtdusppqtdevsjohdijtdnjmjubszddbnqbjhotdjodhbvmrdopufduibuduifddbftbsddjqifsdjtdfbtjmzddsbdlfedczduifdcsvufqgpsdfdbuubdlr key = 17: thecshiftccipherciscalsocknowncasctheccaesarccipherocaftercjuliusccaesarocwhocreputedlycusedctheccipherctocpasscmessagesctochisctroopscduringchiscmilitaryccampaignscincgaulqcnotecthatctheccaesarcciphercisceasilyccrackedcbycthecbrutepforcecattackq Part 3 KeyCode: 17
解决方案
针对凯撒密码暴力破解的通用终止问题,推荐以下几种可行方案:
1. 基于英文常用词匹配判断
英文文本中高频出现的词汇(比如"the"、"and"、"is"、"of")可作为有效语句的判定依据。破解后的文本只要包含多个这类常用词,就大概率是正确解密结果。
实现思路:
- 预先定义常用词集合,比如
std::unordered_set<std::string> common_words = {"the", "and", "is", "of", "to", "in", "it"}; - 对每个密钥解密后的文本,按空格分割成单词;若密文无空格,可滑动匹配3-5个字符的短词组合
- 统计匹配到的常用词数量,当数量超过阈值(比如至少匹配2个常用词,或匹配数占文本长度的15%以上)时,判定为有效解密,终止程序。
代码修改示例:
在解密完成后添加判断逻辑:
// 解密完成后处理 std::istringstream iss(gang); std::string word; int match_count = 0; std::unordered_set<std::string> common_words = {"the", "and", "is", "of", "to", "in", "it"}; while (iss >> word) { if (common_words.count(word)) { match_count++; } } // 设定阈值判断 if (match_count >= 2 || (gang.size() > 0 && match_count * 100 / gang.size() > 15)) { keyCode = key; std::cout << "\nFound valid decryption with key: " << key << std::endl; break; }
2. 基于英文词频统计判断
英文中字母出现频率相对固定(比如'e'占比约12%,'t'约9%,'a'约8%)。计算解密后文本的字母频率,与标准英文频率对比,相似度最高的即为正确密钥。
实现思路:
- 预先定义标准英文字母频率数组:
double standard_freq[] = {8.167, 1.492, 2.782, 4.253, 12.702, 2.228, 2.015, 6.094, 6.966, 0.153, 0.772, 4.025, 2.406, 6.749, 7.507, 1.929, 0.095, 5.987, 6.327, 9.056, 2.758, 0.978, 2.360, 0.150, 1.974, 0.074}; - 对每个解密后的文本,统计每个字母的出现频率
- 计算当前频率与标准频率的相似度(比如用平方差之和,值越小相似度越高)
- 记录相似度最低的密钥,遍历完所有密钥后输出结果,或当相似度低于阈值时直接终止。
3. 让用户手动确认
若担心自动判断误判,可在每个密钥解密后询问用户是否为有效文本,用户确认后立即终止程序。
代码修改示例:
在输出解密文本后添加:
char confirm; std::cout << "\nIs this the correct decryption? (y/n): "; std::cin >> confirm; if (tolower(confirm) == 'y') { keyCode = key; break; }
额外代码优化建议:
alphaArray仅到24,凯撒密码偏移量应为0-25,建议补全25decrypt函数仅处理大写字母,建议兼容小写字母,可先将输入字母转大写再计算- 循环中
i与key
相关产品推荐
相关产品推荐

