一、机械密码学简介
在20世纪,随着机械密码机的出现,密码的复杂性呈爆炸式增长。加密或解密信息的人不再需要理解密码原理即可操作,过去需要数小时才能完成加密的信息现在几乎可以瞬间完成。
无线电通信在第二次世界大战期间成为不可或缺的工具,但由于信号极易被截获,强大的加密技术变得至关重要。德国军方选择采用发明家亚瑟·谢尔比乌斯(Arthur Scherbius)设计的恩尼格玛密码机(Enigma),其加密强度在当时堪称空前。
当按下恩尼格玛键盘上的字母键时,电信号会流入一个扰频盘(转子)。该转子有26个输入和26个输出,内部以随机方式连接——例如,输入1的信号可能从输出14离开。信号会依次通过3个这样的转子,随后被反射,再次反向通过相同的3个转子,最终在灯板上显示加密后的字母。
仅看这一过程,恩尼格玛似乎只是一个单字母替换密码。但其强大之处在于转子会旋转:每按一次键,第一个转子便转动一格;当它转到特定凹槽位置时,会带动第二个转子转动一格,而第二个转子最终会带动第三个转子转动。这使得恩尼格玛成为多字母替换密码机,能够循环使用17,576种(26³种)不同的替换字母表后才重复模式。
为增强安全性,恩尼格玛还允许通过接线板交换键盘上最多10对字母的接线,且转子可拆卸并按6种不同顺序排列。结合转子的17,576种初始旋转位置,机器的总初始配置组合超过15,000,000,000,000,000,000,000(1.5×10²²)种。
只要将机器设置为正确的初始配置,即可解密使用相同设置加密的信息,因此初始配置即为密钥。德国军队每日更换密钥,并每月分发绝密密码本,其中包含恩尼格玛的初始设置信息。
MECHANISED CRYPTOGRAPHY
二、Enigma的内部构造及工作原理
2.1 Enigma的内部构造
SCRAMBLERS(转子):转子是Enigma的核心部分,单一转子的加密方式非常简单,它只使用了一种初级的替换式密码。比如说,E键对应的管脚可能会连到同一个转子另一面的T触点。使恩尼格玛机的加密变得复杂的是多个转子的同时使用,一般在一台恩尼格玛机内有3个或4个转子,在输入信息的同时转子还会转动,这就产生了一种安全得多的加密方式。
当被放进恩尼格玛机后,一个转子可以有26种排列方法。
LAMPBOARD(指示器):显示明文字母键入后所对应的密文字母。
KEYBOARD(键盘):输入明文。
PLUGBOARD(接线板):可最多交换10对在接线板上连接的字母对。
2.2 Enigma的工作原理
密文转换成明文的步骤:
键入密文字母输入电信号,转子转动。电信号通过接线板后被替换为设置好的对应字母信号位。
电信号依次通过3个的转子(通常标记为I、II、III)对信号进行替换,每个转子的内部接线随机(如输入1→输出14)。
电流到达第三个转子后,进入反射器。反射器将信号反向导回,但路径与进入时不同(如输入14→输出9)。
反射后的信号反向通过三个转子(顺序变为III→II→I),再次进行三次替换后得到明文,且转子位置与正向时相同(因为没有再次按键)。
注:转子组具有进位机制,每次按键后,仅第一个转子转动。第二个转子要等第一个转子转动26次之后才会转动,届时依旧仅第二个转子转动,以此类推。即每次键入时,只有一个转子转动。
三转子组合需经过26×26×26=17576次按键后才会恢复初始位置,形成长周期多表替换。
三、小试牛刀
密文:ZYDNI
电信号在到达反射器前,转子的输入位是上层字母(输出位下层)。在到达反射器后,转子的输入位变为下层字母(输出位上层)。
反射器的输入位为下层字母,输出位为上层。
转子在按键按下后就开始转动,在电信号到达之前就转动完成了。
键入第一个字母"Z",转子1转动。(若有多个转子,也只有1转动)
电信号"Z"进入第一个转子的输入位为26对应字母"A"(上层),"A"在转子中的输出位为4。
也就是说电信号会进入反射器的输入位4对应字母"H"(下层),"H"在反射器中的输出位为8。
反射时,电信号进入转子的输入位8对应字母"V"(下层),"V"在转子中的输出位为21。
输出时,21对应的字母是"U",即第一个明文字母为"U"。(本题没有接线板在输入输出时转换字母)
键入第二个密文字母"Y"后,转子1再次转动(若有多个转子,其他依旧不转,直到1转满26次后,转动盘变为第二个,依此类推),其他步骤如上。最后"Y"的明文字母为"L"。
明文:ULTRA
四、代码实现及说明
Github仓库链接:https://github.com/ZzySlhbcf/Cypher-Decoder
4.1 转子
该对象在创建时需要两个变量,一为下层字母序列,二为初始需要移动几次或初始位置的第一个字母(转子在初始化时即完成初始传动)。
由上文我们可以知道,转子由上下两层字母组成。按道理来说,我们应该创建一个元组列表如"[(A,Z),(B,C)]"。这种方法是可行的,但是不难发现如果转子初始没有发生移动的话,上层的字母序列永远是"A-Z",我们只需要对其ASCII码值进行简单运算就可以获得移动后的上层字母序列。
向下传递时输出字母:chr((输入数组下标+初始化转动位数+工作时转动位数) % 26+65(大写字母的起始ASCII))
向上传递时输出下标:(26-初始化转动位数-工作时转动位数+ord(反射器接收到的下标所对应的字母)-65) % 26
Move_Scrambler():该方法用于初始化转子和工作时转动转子,工作转动后将转动次数加一。
Check_Round():该方法用于检查转子是否转动26次,未到26次则返回值为1,表示该转子可进行1次转动。到26次,则将转动次数归零且将转子锁定,返回值为0。
Get_Down_Index():该方法接收向下传输(未到反射器之前)时的输入下标,将其转换为输出的下标。
Get_Up_Index():该方法接收向上传输(到达反射器之后)时的输入下标,将其转换为输出的下标。
4.2 ENIGMA解密装置
该对象在创建时需要四个变量,一为转子序列组,二为反射器序列,三为密文序列,四为接线板字典。
着重讲一下Decoder()方法,遍历密文序列。先将密文字母过一遍接线板字典,后面该字母遍历转子组。遍历时转子组转动标记初始化为1,对应标记的转子需要自检,自检时激活转子,自检通过该转子继续转动;否则该转子停止转动,转子组转动标记后移。转子自检后,密文字母按先下后上的方式通过转子组,得到对应的明文字母。
4.3 主函数
Scrambler1-3:转子序列,若不需要初始化移动,则不需要输入第二个变量。
Reflextor:反射器序列。
Sentence:密文序列。
Plugboard:接线器字典。
Scrambler_list:转子排列顺序,若只有一个转子则列表内只有Scrambler1。
更多游戏资讯请关注:电玩帮游戏资讯专区
电玩帮图文攻略 www.vgover.com