Java仿射移位密码解密代码问题:明文正确但b值错误
仿射密码解密中密钥b值错误的问题排查
问题概述
编写Java代码解密仿射移位密码时,输出的明文正确,但密钥的b值与预期不符。以下是问题代码:
public void solve() { double bestSpell = Double.NEGATIVE_INFINITY; // Start with the worst possible spelling score String bestDecode = ""; // Loop over all possible values of 'a' for (int a = 1; a < 26; a++) { int a_inv = 0; // Find a^-1 (the modular multiplicative inverse of a) for (int i = 1; i < 26; i++) { if ((a * i) % 26 == 1) { a_inv = i; break; } } // If no valid modular inverse, skip this 'a' if (a_inv == 0) continue; // Loop over all possible values of 'b' for (int b = 0; b < 26; b++) { StringBuilder output = new StringBuilder(); // Apply decryption formula for each character in the ciphertext for (int i = 0; i < strippedCT.length(); i++) { if (strippedCT.charAt(i) != ' ') { int x = strippedCT.charAt(i) - 'A'; // Convert character to 0-25 range int decodedValue = (a_inv * (x - b + 26)) % 26; // Ensure non-negative result output.append((char) (decodedValue + 'A')); // Convert back to character } else { output.append(' '); } } // Check the spelling score double currentSpell = sc.spellCheck(output.toString()); // Update best found key if this one is better if (currentSpell > bestSpell) { bestA = a; bestB = b; bestDecode = output.toString(); bestSpell = currentSpell; } } } // Output the best results System.out.println("Solved as mono"); System.out.println("A: " + bestA + " B: " + bestB); System.out.println(bestDecode); this.plaintext = bestDecode; }
核心原因分析
1. 短密文导致多密钥命中相同有效明文
如果测试用的密文长度过短,可能存在多组不同的(a,b)密钥对,解密后得到的短文本恰好是有意义的明文(或拼写得分相同)。此时代码会保留最后一个遍历到的高得分密钥对,而非实际加密时使用的密钥。
2. 拼写检查函数的得分歧义
若拼写检查函数对多个不同明文返回相同的最高得分,代码会选择最后一个遍历到的密钥对。比如短文本中,不同的解密结果可能都是合法单词,得分相同。
3. 密钥概念混淆
仿射密码存在两种密钥表述方式:
- 加密密钥:
(a, b),对应加密公式E(x) = (a*x + b) mod 26 - 解密密钥:
(a⁻¹, c),其中c = (-a⁻¹*b) mod 26,对应解密公式D(y) = (a⁻¹*y + c) mod 26
若你误将解密密钥中的c当作预期的b值,会误以为代码输出的b错误,但实际上代码输出的是正确的加密密钥b。
解决方案
1. 使用更长的测试密文
确保密文长度足够(至少10个字符以上),这样不同密钥对解密出的明文差异会被放大,拼写检查得分会出现明显区分,只有正确的密钥对会得到最高得分。
2. 优化拼写检查逻辑
改进拼写检查函数,让正确明文的得分显著高于其他候选结果。例如:
- 增加完整单词匹配的权重
- 结合英文字母频率统计(E、T等高频字母的出现占比)
3. 验证密钥正确性
找到密钥后,可通过加密反向验证:用得到的(bestA, bestB)加密解密出的明文,看是否与原密文完全一致。若一致,说明密钥正确,只是你的预期存在偏差。
4. 锁定首个最高得分密钥
若需优先保留第一个找到的正确密钥,可保持原代码的更新逻辑(仅当得分更高时替换),这样首个达到最高得分的密钥会被保留,不会被后续得分相同的密钥覆盖。
内容的提问来源于stack exchange,提问作者user27168737
相关产品推荐
相关产品推荐

