수수께끼 기계 구현


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

위치 T의 로터 1 PAIBRCJEKMFLGDQVZNTOWYHXUS은 문자 C를 대신합니다 I.

3 개의 로터가 대체를 수행 한 후 반사기 가 맞습니다 ( R위와 같이 나열 ). 자체 대체를 수행 한 다음 로터를 통해 신호를 다시 반사합니다. 그런 다음 로터는 역순으로 역 치환을 수행합니다.

1 개 대신 대입 로터의 뒷면 교체 수단 AE,이 대입 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 이 동일한 암호화에 사용되는 엔진입니다 아두 이노 수수께끼 기계 시뮬레이터

나는 이해한다고 생각하지만 제대로 작동하지 않는 것 같습니다. 다음은 gist.github.com/JJ-Atkinson/ddd3896fe10d85b3b584 설명하는 요지 입니다.
J Atkin

첫 번째 예에서 "우리가 로터 1, 3 및 5를 사용하는 경우"라고 말했지만 로터 1, 2 및 5 (또는 마지막 로터) 일 것입니다.
코어 덤프

@coredump 수정 됨
Nathan Merrill

로터의 작동 방식에 대한 나의 이해가 여전히 부정확합니까?
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'

나는 이것이 효과가 있다고 생각하지만 참조 impl의 버그가 무엇인지에 따라 다른 출력을 생성합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.