维基少年:树莓派/树莓派谜机
政府通信总部和树莓派基金会 CC-BY-SA 4.0
基于树莓派 OctoPi 教程:https://projects.raspberrypi.org/en/projects/octapi-brute-force-enigma
谜机是一种用于加密和解密信息的设备。它是在20世纪初开发的,在第二次世界大战期间被德国人广泛用于编码他们的军事通信。
谜机最出名的是被阿兰·图灵和他在布莱切利庄园的团队破解,他们开发了破译谜机密码的技术。这在第二次世界大战中盟军的胜利中发挥了至关重要的作用,因为它使他们能够拦截并解码德国人发送的重要信息。
谜机是如何工作的? 在 YouTube 上
谜机由以下部分组成
- 一个用于输入信息的键盘
- 一系列执行加密和解密的转子
- 一个反射器,将电流反射回转子,方向相反
转子可以设置在不同的位置,从而产生大量可能的组合,使得攻击者很难解码信息。
查看你的谜机设置表,你会发现今天的设置如下
转子 | 环设置 | 插线板设置 | 转子起始位置 |
---|---|---|---|
IV I V | 20 05 10 | SX KU QF UN JG TC LA WM OB ZF | FNZ |
这里有一条秘密信息:GON XXLXYFQNZIK
- 打开 Python 3,然后打开名为
decrypt.py
的文件 - 在
chosen_rotors
旁边的绿色引号''
内输入所选转子。 - 现在在
rotor_start
旁边的绿色引号''
内输入转子起始位置的字母。 - 在
message_key
旁边的绿色引号''
内输入信息密钥GON
。 - 输入明文,即秘密信息
XXLXYFQNZIK
。 - 通过按 F5 键运行程序(如果提示保存,请选择“是”)。
使用相同的谜机设置,但不要忘记更改信息密钥:LJE OIVGWVHOVHKAU
- 打开 Python 3,然后打开名为
encrypt.py
的文件 - 再次从设置表中输入所选转子,以及转子起始位置。
- 在
message_key
旁边的绿色引号' '
内输入信息密钥BFR
。 - 运行程序并检查它是否有效——对于明文
RASPBERRYPI
,生成的密文应该是XXLXYFQNZIK
。
现在是时候加密你自己的信息了!
- 选择不同的三个字母的
message_key
并输入。 - 选择不同的明文信息并输入。确保没有空格!
- 运行程序,然后记下加密的密钥和密文,并将它们交给其他人解密。
解密这条信息:GED HYZFQOOVVBBKBWPDZLSL
你需要知道谜机设置才能解密信息!
这是今天的设置。不幸的是,有人在转子设置上洒了墨水 😟
转子 | 环设置 | 插线板设置 | 转子起始位置 |
---|---|---|---|
21 15 16 | KL IT PQ MY XC NF VZ JB SH OG | POW |
字谜是你在知道明文和密文的情况下才能知道的信息。
字谜:WEATHER
密文:VZTLMPU
如果你知道字谜和部分设置,你能使用暴力破解攻击解密这条信息吗?
VZTLMPUSLKTEXYWZWKXDOTT
- 打开 Python 3,然后打开名为
bruteforce.py
的文件。 - 输入字谜和相应的密文。
- 运行暴力破解攻击,以找到转子和信息密钥。
- 现在打开之前使用过的
decrypt.py
程序。 - 输入
rotor start
设置,这次你还需要从设置表中输入环和插线板设置。 - 在暴力破解攻击中找到的
chosen rotors
中输入。 - 这次我们已经知道解密的消息密钥。找到这行代码:
decrypted_message_key = machine.process_text(message_key)
。
将其更改为decrypted_message_key = '???'
,其中???
是在暴力破解攻击中找到的三个字母的密钥。
- 秘密信息是什么?
DHPCMHCQ PXE
18/05/18
ZOC EJDTLFHR BT UKW.
本教程使用Brian Neal 编写的 py-enigma 模块来提供 Enigma 机器功能。
您可以通过在终端中运行此命令在您的 Raspberry Pi(或您的计算机)上安装 py-enigma 的副本
sudo pip3 install py-enigma
维基少年第二次世界大战一书中有一节介绍 Enigma 机器,其中详细介绍了它的工作原理。
了解 Enigma 机器的最佳场所是参观英国米尔顿凯恩斯附近的 布莱切利庄园。
模仿游戏(2014)是一部由本尼迪克特·康伯巴奇主演的电影,他扮演了破译 Enigma 机器的阿兰·图灵。这部电影的年龄分级为 12 级(在美国为 PG-13 级),因此适合年龄较大的儿童和成年人。
树莓派基金会推荐传记Dilly — The Man Who Broke Enigmas(2010,ISBN 9781906447151)由 Mavis Batey 撰写。这本书讲述的是二战期间英国首席密码破译员阿尔弗雷德·迪尔温·诺克斯的故事。
本教程的原始 PDF 文件可在维基共享资源上获得
from enigma.machine import EnigmaMachine
chosen_rotors = '' # Type a space between each rotor e.g. V IV I
rotor_start = ''
message_key = ''
plaintext = 'RASPBERRYPI' # The message you want to encrypt
print("You started with message key " + message_key + " and plaintext " + plaintext)
# Set up the Enigma machine
machine = EnigmaMachine.from_key_sheet(
rotors=chosen_rotors,
reflector='B',
ring_settings='20 5 10',
plugboard_settings='SX KU QP VN JG TC LA WM OB ZF')
# Set the initial position of the Enigma rotors
machine.set_display(rotor_start)
# Encrypt the message key (the three letters you chose)
encrypted_message_key = machine.process_text(message_key)
print("The encrypted message key is " + encrypted_message_key)
# Set the rotor start position to the UNENCRYPTED message key
machine.set_display(message_key)
# The result
ciphertext = machine.process_text(plaintext)
print("The cipher text is: " + ciphertext)
from enigma.machine import EnigmaMachine
chosen_rotors = '' # Type a space between each rotor e.g. V IV I
rotor_start = ''
message_key = ''
plaintext = '' # The message you want to decrypt
print("You started with message key " + message_key + " and plaintext " + plaintext)
# Set up the Enigma machine
machine = EnigmaMachine.from_key_sheet(
rotors=chosen_rotors,
reflector='B',
ring_settings='20 5 10',
plugboard_settings='SX KU QP VN JG TC LA WM OB ZF')
# Set the initial position of the Enigma rotors
machine.set_display(rotor_start)
# Decrypt the message key
decrypted_message_key = machine.process_text(message_key)
print("The decrypted message key is " + decrypted_message_key)
# Set the rotor start position to the DECRYPTED message key
machine.set_display(decrypted_message_key)
# The result
ciphertext = machine.process_text(plaintext)
print("The cipher text is: " + ciphertext)
cribtext = ""
ciphertext = ""
# All possible combinations of rotors
rotors = [ "I II III", "I II IV", "I II V", "I III II",
"I III IV", "I III V", "I IV II", "I IV III",
"I IV V", "I V II", "I V III", "I V IV",
"II I III", "II I IV", "II I V", "II III I",
"II III IV", "II III V", "II IV I", "II IV III",
"II IV V", "II V I", "II V III", "II V IV",
"III I II", "III I IV", "III I V", "III II I",
"III II IV", "III II V", "III IV I", "III IV II",
"III IV V", "IV I II", "IV I III", "IV I V",
"IV II I", "IV II III", "IV I V", "IV II I",
"IV II III", "IV II V", "IV III I", "IV III II",
"IV III V", "IV V I", "IV V II", "IV V III",
"V I II", "V I III", "V I IV", "V II I",
"V II III", "V II IV", "V III I", "V III II",
"V III IV", "V IV I", "V IV II", "V IV III" ]
def find_rotor_start( rotor_choice, ciphertext, cribtext ):
from enigma.machine import EnigmaMachine
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
machine = EnigmaMachine.from_key_sheet(
rotors=rotor_choice,
reflector='B',
ring_settings='21 15 16',
plugboard_settings='KL IT PQ MY XC NF VZ JB SH OG')
# Search over all possible rotor starting positions
for i in range(len(alphabet)): # search for rotor 1 start position
for j in range(len(alphabet)): # search for rotor 2 start position
for k in range(len(alphabet)): # search for rotor 3 start position
# Generate a possible rotor start position
start_pos = alphabet[i] + alphabet[j] + alphabet[k]
# Set machine initial starting position and attempt to decrypt
machine.set_display(start_pos)
plaintext = machine.process_text(ciphertext)
#print("Plain: " + plaintext + ", Crib: " + cribtext)
# Check if decrypted text is the same as the crib text
if (plaintext == cribtext):
return( rotor_choice, start_pos )
return( rotor_choice, "null" )
print("Brute force crypt attack on Enigma message " + ciphertext)
print("Crib text " + cribtext )
# Try all rotor settings
for rotor_setting in rotors:
print("Trying rotors " + rotor_setting)
rotor_choice, start_pos = find_rotor_start( rotor_setting, ciphertext, cribtext )
if (start_pos != "null"):
print("Machine setting found!")
print("Rotors: " + rotor_choice)
print("Message key: " + start_pos)
print("Using crib " + cribtext)
exit(0)