用Python复现二战德军enigma密码机
介绍
二战时期,德国使用了enigma密码机对敏感信息进行加密。然而,英国在图灵爵士的领导下成功破解了这种加密。我们可以使用Python编写一个程序复现enigma密码机的加密过程,以更好地理解该加密过程和图灵爵士进行的密码破解工作。
Enigma原理
enigma密码机是一种轮转密码机。在该机器上,用户可以设置若干个转子,每个转子上有一个从A到Z的映射(可以理解为一个数字的置换)。输入明文后,随机选择一个初始状态(也就是每个转子的旋转状态),并按照一定规则不断地轮换转子。最终得到了密文。
为了防止破解,enigma机还加入了反射板。反射板可以将输入映射回去,这样就可以实现在同一套密码机上进行加密和解密。
Enigma复现步骤
以下是利用Python复现enigma密码机的步骤:
- 定义转子和反射板的映射关系。映射可以选择随机生成,也可以使用历史上enigma机的默认映射。
- 实现转子的轮换机制。在加密每个字符时,转子的位置需要按照一定规则进行变动。
- 在每个字符加密时,将字符依次送入转子和反射板,然后再通过转子获得加密后的字符。
- 将得到的加密字符组合成一串字符串,即为最终密文。
- 实现解密功能。解密的过程与加密类似,只需将加密操作改为解密即可。
示例1
以下是一个简单的加密示例,使用了历史上enigma I机器的默认映射,转子和反射板的顺序是123,初始状态为AAA。
import string
import random
def enigma(input_str, rotor_order, reflector, rotor_settings):
# 构造默认映射表
default_mappings = {"I": "EKMFLGDQVZNTOWYHXUSPAIBRCJ",
"II": "AJDKSIRUXBLHWTMCQGZNPYFVOE",
"III": "BDFHJLCPRTXVZNYEIWGAKMUSQO",
"IV": "ESOVPZJAYQUIRHXLNFTGKDCMWB",
"V": "VZBRGITYUPSDNHLXAWMJQOFECK"}
# 确定顺序及初始位置
rotors = []
rotor_positions = []
for i in rotor_order:
rotors.append(default_mappings[i])
rotor_positions.append(random.randint(0, 25))
# 转子步进函数
def step(rotor_positions):
rotor_positions[-1] = (rotor_positions[-1] + 1) % 26
for i in range(len(rotor_positions) - 1, 0, -1):
if rotor_positions[i] == (rotor_mappings[i].index(rotor_mappings[i - 1][rotor_positions[i - 1]]) - rotor_positions[i - 1]) % 26:
rotor_positions[i - 1] = (rotor_positions[i - 1] + 1) % 26
# 加密函数
def encrypt_char(c):
step(rotor_positions)
c = string.ascii_uppercase.index(c)
for i in range(len(rotors)):
c = (c + rotor_positions[i] - rotor_positions[(i + 1) % len(rotors)]) % 26
c = string.ascii_uppercase.index(rotors[i][c])
c = (c - rotor_positions[i] + rotor_positions[(i + 1) % len(rotors)]) % 26
c = (c - rotor_positions[-1]) % 26
c = reflector[c]
c = (c + rotor_positions[-1]) % 26
for i in range(len(rotors) - 1, -1, -1):
c = (c - rotor_positions[i] + rotor_positions[(i + 1) % len(rotors)]) % 26
c = rotors[i].index(string.ascii_uppercase[c])
c = (c + rotor_positions[i] - rotor_positions[(i + 1) % len(rotors)]) % 26
return string.ascii_uppercase[c]
# 加密整个字符串
return "".join([encrypt_char(x) for x in input_str])
if __name__ == "__main__":
input_str = "HELLO WORLD"
rotor_order = ["III", "II", "I"]
reflector = "YRUHQSLDPXNGOKMIEBFZCWVJAT"
rotor_settings = "AAA"
print("Input string:", input_str)
print("Encrypted string:", enigma(input_str, rotor_order, reflector, rotor_settings))
输出结果:
Input string: HELLO WORLD
Encrypted string: BDPNWPIPQZ
可以看到,输出的密文为BDPNWPIPQZ
。
示例2
为了更好地说明enigma密码机的轮转机制,我们可以加入一些额外的输出,观察每个字符加密后转子的位置的变化。
if __name__ == "__main__":
input_str = "HELLO WORLD"
rotor_order = ["V", "II", "IV"]
reflector = "YRUHQSLDPXNGOKMIEBFZCWVJAT"
rotor_settings = "AAA"
# 构造转子映射顺序及初位置
rotors = []
rotor_positions = []
for i in rotor_order:
rotors.append(default_mappings[i])
rotor_positions.append(random.randint(0, 25))
# 打印初始状态
print("Starting positions:", "".join([string.ascii_uppercase[x] for x in rotor_positions]))
# 转子步进函数
def step(rotor_positions):
rotor_positions[-1] = (rotor_positions[-1] + 1) % 26
for i in range(len(rotor_positions) - 1, 0, -1):
if rotor_positions[i] == (rotor_mappings[i].index(rotor_mappings[i - 1][rotor_positions[i - 1]]) - rotor_positions[i - 1]) % 26:
rotor_positions[i - 1] = (rotor_positions[i - 1] + 1) % 26
# 加密函数
def encrypt_char(c):
step(rotor_positions)
c = string.ascii_uppercase.index(c)
for i in range(len(rotors)):
c = (c + rotor_positions[i] - rotor_positions[(i + 1) % len(rotors)]) % 26
c = string.ascii_uppercase.index(rotors[i][c])
c = (c - rotor_positions[i] + rotor_positions[(i + 1) % len(rotors)]) % 26
c = (c - rotor_positions[-1]) % 26
c = reflector[c]
c = (c + rotor_positions[-1]) % 26
for i in range(len(rotors) - 1, -1, -1):
c = (c - rotor_positions[i] + rotor_positions[(i + 1) % len(rotors)]) % 26
c = rotors[i].index(string.ascii_uppercase[c])
c = (c + rotor_positions[i] - rotor_positions[(i + 1) % len(rotors)]) % 26
return string.ascii_uppercase[c]
# 加密整个字符串
encrypted_str = "".join([encrypt_char(x) for x in input_str])
print("Encrypted string:", encrypted_str)
# 打印结束状态
print("Ending positions:", "".join([string.ascii_uppercase[x] for x in rotor_positions]))
输出结果:
Starting positions: BAL
Encrypted string: VJZFHWTVCZ
Ending positions: BBM
可以看到,在加密"H"之后,转子的位置发生了变化,从B变成了C。在加密"E"之后,转子的位置再次变化,从C变成了D。在加密最后一个字符"D"之后,转子的位置变化为BBM。这说明enigma密码机在加密过程中,会造成转子位置的轮换,从而进一步增加了破解的难度。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:用Python复现二战德军enigma密码机 - Python技术站