跳转到内容

维基少年:树莓派/树莓派谜机

来自维基教科书,开放世界中的开放书籍
布莱切利庄园

政府通信总部和树莓派基金会 CC-BY-SA 4.0

基于树莓派 OctoPi 教程:https://projects.raspberrypi.org/en/projects/octapi-brute-force-enigma

什么是谜机?

[编辑 | 编辑源代码]

谜机是一种用于加密和解密信息的设备。它是在20世纪初开发的,在第二次世界大战期间被德国人广泛用于编码他们的军事通信。

谜机最出名的是被阿兰·图灵和他在布莱切利庄园的团队破解,他们开发了破译谜机密码的技术。这在第二次世界大战中盟军的胜利中发挥了至关重要的作用,因为它使他们能够拦截并解码德国人发送的重要信息。

谜机是如何工作的?

[编辑 | 编辑源代码]

谜机是如何工作的? 在 YouTube 上

谜机由以下部分组成

  • 一个用于输入信息的键盘
  • 一系列执行加密和解密的转子
  • 一个反射器,将电流反射回转子,方向相反

转子可以设置在不同的位置,从而产生大量可能的组合,使得攻击者很难解码信息。

工作表

[编辑 | 编辑源代码]

查看你的谜机设置表,你会发现今天的设置如下

转子环设置插线板设置转子起始位置
IV I V20 05 10SX KU QF UN JG TC LA WM OB ZFFNZ

解密一条信息

[编辑 | 编辑源代码]

解密后的信息是什么?

[编辑 | 编辑源代码]

这里有一条秘密信息:GON XXLXYFQNZIK

  1. 打开 Python 3,然后打开名为 decrypt.py 的文件
  2. chosen_rotors 旁边的绿色引号 '' 内输入所选转子。
  3. 现在在 rotor_start 旁边的绿色引号 '' 内输入转子起始位置的字母。
  4. message_key 旁边的绿色引号 '' 内输入信息密钥 GON
  5. 输入明文,即秘密信息 XXLXYFQNZIK
  6. 通过按 F5 键运行程序(如果提示保存,请选择“是”)。

你能解密这条信息吗?

[编辑 | 编辑源代码]

使用相同的谜机设置,但不要忘记更改信息密钥:LJE OIVGWVHOVHKAU

加密一条信息

[编辑 | 编辑源代码]
  1. 打开 Python 3,然后打开名为 encrypt.py 的文件
  2. 再次从设置表中输入所选转子,以及转子起始位置。
  3. message_key 旁边的绿色引号 ' ' 内输入信息密钥 BFR
  4. 运行程序并检查它是否有效——对于明文 RASPBERRYPI,生成的密文应该是 XXLXYFQNZIK

现在是时候加密你自己的信息了!

  • 选择不同的三个字母的 message_key 并输入。
  • 选择不同的明文信息并输入。确保没有空格!
  • 运行程序,然后记下加密的密钥和密文,并将它们交给其他人解密。

解密这条信息:GED HYZFQOOVVBBKBWPDZLSL

暴力破解攻击

[编辑 | 编辑源代码]

你需要知道谜机设置才能解密信息!

这是今天的设置。不幸的是,有人在转子设置上洒了墨水 😟

转子环设置插线板设置转子起始位置
21 15 16KL IT PQ MY XC NF VZ JB SH OGPOW

字谜是你在知道明文和密文的情况下才能知道的信息。

字谜:WEATHER
密文:VZTLMPU

如果你知道字谜和部分设置,你能使用暴力破解攻击解密这条信息吗?

VZTLMPUSLKTEXYWZWKXDOTT

暴力破解攻击

[编辑 | 编辑源代码]
  1. 打开 Python 3,然后打开名为 bruteforce.py 的文件。
  2. 输入字谜和相应的密文。
  3. 运行暴力破解攻击,以找到转子和信息密钥。

解密信息

[编辑 | 编辑源代码]
  1. 现在打开之前使用过的 decrypt.py 程序。
  2. 输入 rotor start 设置,这次你还需要从设置表中输入环和插线板设置。
  3. 在暴力破解攻击中找到的chosen rotors中输入。
  4. 这次我们已经知道解密的消息密钥。找到这行代码: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 文件可在维基共享资源上获得

encrypt.py

[编辑 | 编辑源代码]
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)

decrypt.py

[编辑 | 编辑源代码]
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)

bruteforce.py

[编辑 | 编辑源代码]
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)
华夏公益教科书