Java 中的 Vigenere/Polyalphabetic Cipher Decoder/Decrypter/Breaker
Posted
技术标签:
【中文标题】Java 中的 Vigenere/Polyalphabetic Cipher Decoder/Decrypter/Breaker【英文标题】:Vigenere/Polyalphabetic Cipher Decoder/Decrypter/Breaker in Java 【发布时间】:2012-12-28 22:48:18 【问题描述】:我正在尝试开发一个程序,对使用 Vigenere 密码编码的消息进行编码、解码和破解加密。我被卡住的地方是破坏消息(没有密钥)的[加密]。我知道如何去做,但我不知道如何编码。我的想法如下:
该程序将系统地生成潜在的密钥,长度从 1 开始到 26 结束。这些密钥将包含英文字母表中的字母并且不区分大小写。对于每个密钥长度(从 1 到 26 的任意位置),密钥将用字母“a”填充,然后程序将检查它们的密钥是否正确(我有另一种方法)。如果他们的键不正确,那么最后一个位置的字母将被旋转到字母表中的下一个字母。一旦最后一个字母经过所有 26 个可能的位置,倒数第二个字母将旋转,然后最后一个字母和倒数第二个字母将相应旋转,依此类推(一直回到第一个[potential] 键的字母)。每次生成新密钥时,都会使用单独的方法检查 [潜在] 密钥,并在找到正确密钥时停止该方法。密钥创建过程将如下所示:
[starting with keys that are only 1 letter long]
a
b
c
...
x
y
z
[now the potential key length becomes two]
aa
ab
ac
ad
...
zw
zx
zy
zz
[eventually the potential key length becomes 26]
aaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaab
aaaaaaaaaaaaaaaaaaaaaaaaac
aaaaaaaaaaaaaaaaaaaaaaaaad
...
zzzzzzzzzzzzzzzzzzzzzzzzzw
zzzzzzzzzzzzzzzzzzzzzzzzzx
zzzzzzzzzzzzzzzzzzzzzzzzzy
zzzzzzzzzzzzzzzzzzzzzzzzzz
(希望你能看到那里的模式)
如果有人拥有或知道如何执行此操作的代码,或者可以帮助指导完成编写此代码所需的步骤,将不胜感激。
谢谢!
【问题讨论】:
我们不会为您编写代码。发表一些具体的问题,并向我们展示您目前编写的一些代码。 首先,为什么这个标记为递归(在我看来更像是普通迭代)和第二个暴力破解 vigenere 密码可能不是最好的方法。 到目前为止我什么都没有,就像我说的那样,提出步骤的任何解释/帮助也很有帮助。 :) @fvu 你有什么建议? (请记住,考虑到我不是专家,这将相对简单) 这是不切实际的,你需要绝对巨大的迭代次数——大约 6*10^36。我要么先阅读所有关于 Vigenere 的可用文献(以及用于简化问题的技巧),要么找到其他一些难题来解决。 【参考方案1】:编辑(现在我已经算好了)
您需要迭代大约 6*10^36 种可能的组合 - 最大的 long
值约为 9*10^18 - 小得多 的数字。
话虽如此,假设您找到了一种优化的方法来迭代组合,您可以每秒生成和比较一万亿 (10^12) 个组合(比普通开发人员的机器快得多) ,并且您可以在 100 万台机器上并行化它 - 这将是每年 (60*60*24*365*10^12)*10^6,或者每年检查大约 3*10^25 个组合。
以如此惊人的速度,仍然需要大约 1900 亿年才能遍历所有组合。
我强烈建议您研究另一种方法来实现您的目标,而不是尝试每一个键。
现在(回到我原来的答案),如果你有一个合理大小的键子集想要迭代,我可以想象用一个直接向上的数字循环做这样的事情,它只是将数字转换为修改后的基数- 26 为密钥。
一些伪代码:
public void runAlgorithm ()
for (int i=startKey; i<endKey; i++)
String key = toBase26(i);
testKey(key);
使用 this hexavigesimal converter from wikipedia 之类的东西作为 toBase26
的 impl(复制如下):
public static String toBase26(int number)
number = Math.abs(number);
String converted = "";
// Repeatedly divide the number by 26 and convert the
// remainder into the appropriate letter.
do
int remainder = number % 26;
converted = (char)(remainder + 'A') + converted;
number = (number - remainder) / 26;
while (number > 0);
return converted;
【讨论】:
您的解决方案的唯一问题是它会产生如下输出:A、B、C、D、E、F、G、H、I、J、K、L、M、N、 O,P,Q,R,S,T,U,V,W,X,Y,Z,BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,BK,BL,BM, BN,BO,BP,BQ,BR,BS,BT,BU,BV,BW,BX,BY,BZ,CA,CB,CC,CD,CE,CF,CG,CH,CI,CJ,CK,CL, CM, CN, CO, CP, CQ, CR, CS, CT, CU, CV, CW, CX, CY, CZ...在添加另一个字母的地方,第一个字母远离应有的位置(例如,'b ' 而不是 'a'),但除此之外它非常接近。谢谢! 很少完美,但它应该为您指出足够正确的方向,您可以对其进行调整以做您想做的事情。 我现在正在计算潜在的键数,这是一个巨大的数字(这并不奇怪),我已经尝试编辑您的代码以满足我的需求,但似乎没有任何效果...有什么想法吗? [可能]键的数量是:6,402,364,363,415,443,603,228,541,259,936,211,926...哇! 是的,这比long
还要大。开始听起来类似于另一个"iterate over all teh guids" 问题...以上是关于Java 中的 Vigenere/Polyalphabetic Cipher Decoder/Decrypter/Breaker的主要内容,如果未能解决你的问题,请参考以下文章