Впроваджуйте машину Enigma


18

Машина Enigma - це досить складна шифрована машина, яку використовують німці та інші для шифрування своїх повідомлень. Ваша робота з впровадження цієї машини *.

Крок 1, Обертання

Наша машина енігми має 3 гнізда для роторів і 5 доступних роторів для кожного з цих слотів. Кожен ротор має 26 різних можливих положень (від Aдо Z). Кожен ротор має заздалегідь задане положення висічки :

Rotor  Notch
------------
1      Q
2      E
3      V
4      J
5      Z

Під час натискання клавіші відбуваються наступні дії:

  1. Ротор в слоті 1 обертається
  2. Якщо ротор у гнізді 1 просувається повз його виїмку, то він обертає ротор у слоті 2.
  3. Якщо ротор у гнізді 2 знаходиться на виїмці (але не просто перемістився туди), обидва ротора 2 і 3 обертаються один раз.

Якщо ми використовуємо ротори 1,3,5 , і вони знаходяться в робочому положенні , P,U,Hто послідовність позицій: P,U,H> Q,U,H> R,V,H>S,W,I

Крок 2, Заміна

Кожен з роторів виконує просту заміну символів. Далі представлена ​​діаграма кожного з роторів у Aположенні:

  ABCDEFGHIJKLMNOPQRSTUVWXYZ
  --------------------------
1 EKMFLGDQVZNTOWYHXUSPAIBRCJ
2 AJDKSIRUXBLHWTMCQGZNPYFVOE
3 BDFHJLCPRTXVZNYEIWGAKMUSQO
4 ESOVPZJAYQUIRHXLNFTGKDCMWB
5 VZBRGITYUPSDNHLXAWMJQOFECK
R YRUHQSLDPXNGOKMIEBFZCWVJAT

Ротор 1 у положенні T є PAIBRCJEKMFLGDQVZNTOWYHXUS, що замінить букву Cна I.

Після того, як три ротора виконають свою заміну, відбивають рефлектор (перераховано Rвище). Він виконує власну підстановку, а потім відбиває сигнал назад через ротори. Потім ротори виконують зворотну заміну в зворотному порядку.

Оборотні кошти заміни , що замість ротора 1 замінюють Aз E, вона заміщає EзA

Прорізи заповнені роторами 1,2,3, всі в положенні A. Лист Qпростежує шлях Q>X>V>Mчерез ротори. Mвідображає, до Oякого далі йде зворотний шлях O>Z>S>S. Тому Aзаміщений на S.

Введення-виведення

Вас передають:

  1. Список 3 роторів (як цілі числа)
  2. Список 3-х положень старту ротора (як літери)
  3. Рядок, який потрібно зашифрувати.

Ви можете припустити, що ваш вклад буде добре сформований, а всі символи будуть великими літерами, без пробілів.

Ви повинні повернути зашифрований рядок.

Ви можете додатково прийняти ротори, виїмки та відбивачі як вхідні дані. Для тих, хто не може зняти з балу 95 байт, як95 = ceil(log2(26 letters ^(26*6 rotors +5 notches))/8 bytes)

Тестові справи

Rotor Position Input              Output
4,1,5 H,P,G    AAAAAAAAA          RPWKMBZLN
1,2,3 A,A,A    PROGRAMMINGPUZZLES RTFKHDOVZSXTRMVPFC
1,2,3 A,A,A    RTFKHDOVZSXTRMVPFC PROGRAMMINGPUZZLES
2,5,3 U,L,I    GIBDZNJLGXZ        UNCRACKABLE

Мою реалізацію можна знайти на Github . Я перевірив це, але, можливо, у моїй роботі є помилки (це означає, що мої тестові випадки, ймовірно, неправильні).

* Я намагався зробити це максимально точним , але через розбіжності між машинами, я можу помилитися з деякими деталями. Однак ваше завдання - реалізувати те, що я описав, навіть якщо я неточний. Я не включаю плату для простоти


1
Це правильна реалізація для алгоритму шифрування, який використовується в Enigma I, M3 & M4. Усі налаштування присутні, а також працює плата та перемикач Uhr: https://github.com/arduinoenigma/ArduinoEnigmaEngineAndUhr Це той самий механізм шифрування, який використовується у симуляторі машини Arduino Enigma

Я думаю, що я розумію, але це, здається, не працює правильно. Ось суть, яка пояснює це gist.github.com/JJ-Atkinson/ddd3896fe10d85b3b584 .
J Atkin

У першому прикладі ви сказали, "якщо ми використовуємо ротори 1, 3 і 5", але я думаю, що це були б ротори 1, 2 і 5 (або все, що стосується останнього).
coredump

@coredump Виправлено
Натан Меррілл

Чи моє розуміння того, як працюють ротори, все ще неправильне?
J Atkin

Відповіді:


4

Пітон 3, 403 байти

Я думаю, що це працює правильно. Ротори перейшли до нього:

def z(p,o,m,f,g,h):
 O=ord;b=lambda a:a[1:]+a[:1];d=lambda a:chr(a+O('A'));e=lambda a:O(a)-O('A');i=[list(g[i-1])for i in p];j=[f[i-1]for i in p];i=[x[e(y):]+x[:e(y)]for x,y in zip(i,o)];k=[]
 for l in m:
  if i[0][0]==j[0]:i[1]=b(i[1])
  elif i[1][0]==j[1]:i[1]=b(i[1]);i[2]=b(i[2])
  i[0]=b(i[0]);c=l
  for n in i:c=n[e(c)]
  c=h[e(c)]
  for n in reversed(i):c=d(n.index(c))
  k+=[c]
 return''.join(k)

fє виїмкою, gє роторами і hє відбивачем.

Безумовно:

shift = lambda rotor: rotor[1:] + rotor[:1]
letter = lambda num: chr(num + ord('A'))
number = lambda chr: ord(chr) - ord('A')


def encode(rotors, rotorStart, message, defaultRotors, reflector, rotorNotchPositions):
    usedRotors = [list(defaultRotors[i - 1]) for i in rotors]
    notches = [rotorNotchPositions[i - 1] for i in rotors]
    usedRotors = [rotor[number(offset):] + rotor[:number(offset)] for rotor, offset in zip(usedRotors, rotorStart)]

    sub = []

    for char in message:
        # print([''.join(rotor) for rotor in usedRotors])
        if usedRotors[0][0] == notches[0]:
            usedRotors[1] = shift(usedRotors[1])
        elif usedRotors[1][0] == notches[1]:
            usedRotors[1] = shift(usedRotors[1])
            usedRotors[2] = shift(usedRotors[2])

        usedRotors[0] = shift(usedRotors[0])

        c = char
        for rotor in usedRotors:
            c = rotor[number(c)]
        c = reflector[number(c)]
        for rotor in reversed(usedRotors):
            c = letter(rotor.index(c))
        sub += [c]
        print([''.join(rotor) for rotor in usedRotors], char, c, message)

    return ''.join(sub)

rotorNotchPositions = 'QEVJZ'
*defaultRotors, reflector = [
    #ABCDEFGHIJKLMNOPQRSTUVWXYZ#
    "EKMFLGDQVZNTOWYHXUSPAIBRCJ",  # 1
    "AJDKSIRUXBLHWTMCQGZNPYFVOE",  # 2
    "BDFHJLCPRTXVZNYEIWGAKMUSQO",  # 3
    "ESOVPZJAYQUIRHXLNFTGKDCMWB",  # 4
    "VZBRGITYUPSDNHLXAWMJQOFECK",  # 5
    "YRUHQSLDPXNGOKMIEBFZCWVJAT"   # R
]

#             Rotor       Position        Input                 Output
assert encode((4, 1, 5), ('H', 'R', 'G'), 'AAAAAAAAA',
              defaultRotors, reflector, rotorNotchPositions) == 'PXSHJMMHR'
assert encode((1, 2, 3), ('A', 'A', 'A'), 'PROGRAMMINGPUZZLES',
              defaultRotors, reflector, rotorNotchPositions) == 'RTFKHDOCCDAHRJJDFC'
assert encode((1, 2, 3), ('A', 'A', 'A'), 'RTFKHDOVZSXTRMVPFC',
              defaultRotors, reflector, rotorNotchPositions) == 'PROGRAMRXGVGUVFCES'
assert encode((2, 5, 3), ('U', 'L', 'I'), 'GIBDZNJLGXZ',
              defaultRotors, reflector, rotorNotchPositions) == 'UNCRAUPSCTK'

Я думаю, що це працює, але це дає інший вихід, завдяки чому (я думаю) є помилкою в опорному імпл.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.