Enigma w Konsoli
Oto kompletny, gotowy do uruchomienia kod w Pythonie, który emuluje działanie 3-wirnikowej maszyny Enigma I (najpopularniejszego modelu wojskowego) wraz z odwracaczem (reflektorem) oraz pełną mechanizmem obrotu bębnów (wliczając w to słynny krok potrójny, czyli double stepping).
Kod został napisany tak, aby po uruchomieniu działał jako automatyczny wygaszacz / animacja w tle. Generuje losowy tekst, a następnie litera po literze pokazuje na żywo aktualną pozycję wirników (ich obrót) oraz proces szyfrowania.

Kod symulatora Enigmy (Python 3)
Możesz skopiować poniższy kod i zapisać go jako plik np. enigma_stream.py. Wymaga jedynie standardowej biblioteki Pythona (nie musisz niczego instalować przez pip).
import time
import random
import sys
class EnigmaMachine:
def __init__(self):
# Definicje okablowania historycznych wirników Enigmy I
self.ROTOR_WIRING = {
'I': "EKMFLGDQVZNTOWYHXUSPAIBRCJ",
'II': "AJDKSIRUXBLHWTMCQGZNPYFVOE",
'III': "BDFHJLCPRTXVZNYEIWGAKMUSQO"
}
# Punkty obrotu (Notch) - moment, w którym wirnik popycha następny
self.ROTOR_NOTCH = {'I': 'Q', 'II': 'E', 'III': 'V'}
# Definicja reflektora (Reflektor B)
self.REFLECTOR = "YRUHQSLDPXNGOKMIEBFZCWVJAT"
# Początkowe ustawienie bębnów (np. 'A', 'A', 'A')
self.r_pos = [0, 0, 0] # [Lewy, Środkowy, Prawy]
self.rotors = ['I', 'II', 'III']
def set_positions(self, pos_str):
"""Ustawia początkowe litery wirników, np. 'XYZ'"""
self.r_pos = [ord(c) - ord('A') for c in pos_str.upper()]
def _rotate(self):
"""Mechanizm obrotu wirników uwzględniający Double Stepping (potrójny krok)"""
# Pobranie aktualnych liter w miejscach karbów (notch)
r_notch = self.ROTOR_NOTCH[self.rotors[0]] # Lewy
m_notch = self.ROTOR_NOTCH[self.rotors[1]] # Środkowy
p_notch = self.ROTOR_NOTCH[self.rotors[2]] # Prawy
r_char = chr(self.r_pos[0] + 65)
m_char = chr(self.r_pos[1] + 65)
p_char = chr(self.r_pos[2] + 65)
# Flagi obrotu
rotate_left = False
rotate_mid = False
rotate_right = True # Prawy wirnik obraca się zawsze przy każdym klawiszu
# Double stepping: jeśli środkowy jest na pozycji karbu, obraca siebie i lewy
if m_char == m_notch:
rotate_left = True
rotate_mid = True
# Jeśli prawy jest na pozycji karbu, obraca środkowy
elif p_char == p_notch:
rotate_mid = True
# Zastosowanie obrotów w pamięci
if rotate_left: self.r_pos[0] = (self.r_pos[0] + 1) % 26
if rotate_mid: self.r_pos[1] = (self.r_pos[1] + 1) % 26
if rotate_right: self.r_pos[2] = (self.r_pos[2] + 1) % 26
def _map_forward(self, char_idx, rotor_name, pos):
"""Przepływ sygnału od klawiatury do reflektora"""
shift_idx = (char_idx + pos) % 26
out_char = self.ROTOR_WIRING[rotor_name][shift_idx]
out_idx = (ord(out_char) - ord('A') - pos) % 26
return out_idx
def _map_backward(self, char_idx, rotor_name, pos):
"""Przepływ powrotny sygnału od reflektora do żarówki"""
shift_idx = (char_idx + pos) % 26
out_char = chr(self.ROTOR_WIRING[rotor_name].index(chr(shift_idx + 65)) + 65)
out_idx = (ord(out_char) - ord('A') - pos) % 26
return out_idx
def encrypt_char(self, char):
"""Szyfruje pojedynczy znak i obraca bębny"""
if not char.isalpha():
return char
char = char.upper()
self._rotate()
idx = ord(char) - ord('A')
# Przejście przez wirniki w prawo -> lewo
idx = self._map_forward(idx, self.rotors[2], self.r_pos[2]) # Prawy
idx = self._map_forward(idx, self.rotors[1], self.r_pos[1]) # Środkowy
idx = self._map_forward(idx, self.rotors[0], self.r_pos[0]) # Lewy
# Reflektor
idx = (ord(self.REFLECTOR[idx]) - ord('A')) % 26
# Przejście powrotne lewo -> prawo
idx = self._map_backward(idx, self.rotors[0], self.r_pos[0]) # Lewy
idx = self._map_backward(idx, self.rotors[1], self.r_pos[1]) # Środkowy
idx = self._map_backward(idx, self.rotors[2], self.r_pos[2]) # Prawy
return chr(idx + 65)
# --- SKRYPT AUTOMATYCZNEJ PREZENTACJI W TLE ---
if __name__ == "__main__":
enigma = EnigmaMachine()
enigma.set_positions("AAA")
print("\033[H\033[J") # Czyszczenie ekranu terminala
print("=============================================================")
print(" SYMULACJA HISTORII ENIGMY I — TRANSMISJA AUTOMATYCZNA")
print("=============================================================\n")
try:
while True:
# Generowanie losowej "wiadomości wojskowej" do zaszyfrowania
length = random.randint(15, 30)
raw_text = "".join(random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ") for _ in range(length))
for char in raw_text:
cipher_char = enigma.encrypt_char(char)
# Odczyt aktualnego stanu bębnów jako litery (np. K - M - A)
pos_str = f"[{chr(enigma.r_pos[0]+65)}][{chr(enigma.r_pos[1]+65)}][{chr(enigma.r_pos[2]+65)}]"
# Formatowanie linii wyświetlania w terminalu
sys.stdout.write(f"\rBĘBNY: {pos_str} | WEJŚCIE: {char} ---> SZYFR: {cipher_char}")
sys.stdout.flush()
# Szybkość "obracania się" mechanizmu (0.15 sekundy na znak)
time.sleep(0.15)
# Mała przerwa między paczkami danych, udająca transmisję kolejnej wiadomości
print(" [OK]")
time.sleep(1.0)
except KeyboardInterrupt:
print("\n\nZatrzymano symulację.")
Jak to wygląda i działa w tle podczas wykładu?
1. Kod uruchamia nieskończoną pętlę (while True). Nie musisz nic klikać.
2. W terminalu zobaczysz nieustannie odświeżającą się linię tekstu.
3. Wskaźnik BĘBNY: [A][A][B] zacznie gwałtownie zmieniać litery. Zobaczysz, że prawy wirnik zmienia się co krok, środkowy raz na 26 kroków, a lewy jeszcze rzadziej – dokładnie tak, jak w fizycznym urządzeniu.
4. Całość daje bardzo surowy, "kryptograficzny" efekt tekstowy, idealnie pasujący jako dynamiczne tło, kiedy opowiadasz o matematycznym podejściu von Neumanna do systemów binarnych i przetwarzania danych.