ติดตั้ง Enigma Machine


18

เครื่อง Enigma เป็นเครื่องเข้ารหัสที่ค่อนข้างซับซ้อนซึ่งชาวเยอรมันและคนอื่นใช้ในการเข้ารหัสข้อความ เป็นหน้าที่ของคุณที่จะใช้เครื่องนี้ *

ขั้นตอนที่ 1 การหมุน

เครื่องปริศนาของเรามี 3 ช่องสำหรับโรเตอร์และโรเตอร์ที่มี 5 ช่องสำหรับแต่ละช่องเหล่านี้ โรเตอร์แต่ละตัวมีตำแหน่งที่เป็นไปได้ 26 แบบที่แตกต่างกัน (จากAถึงZ) โรเตอร์แต่ละตัวมีตำแหน่งรอยที่กำหนดไว้ล่วงหน้า:

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

เมื่อกดปุ่มจะเกิดขั้นตอนต่อไปนี้:

  1. โรเตอร์ใน Slot 1 หมุน
  2. ถ้าโรเตอร์ในช่อง 1 เคลื่อนผ่านรอยบากมันก็จะหมุนโรเตอร์ในช่อง 2
  3. ถ้าโรเตอร์ใน Slot 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ซึ่งจะใช้แทนตัวอักษรสำหรับCI

หลังจากที่ทั้งสามใบพัดทำการทดแทนตัวสะท้อนแสงจะถูกกระทบ (ตามที่แสดงRด้านบน) มันทำการทดแทนตัวเองแล้วสะท้อนสัญญาณกลับผ่านใบพัด จากนั้นใบพัดจะทำการสับเปลี่ยนแบบย้อนกลับตามลำดับย้อนกลับ

วิธีการเปลี่ยนตัวย้อนกลับว่าแทนที่จะโรเตอร์ 1 ทดแทนAด้วยEก็ทดแทนEด้วยA

สล็อตจะเต็มไปด้วยใบพัด 1,2,3 Aทั้งหมดในตำแหน่ง ตัวอักษรQเดินตามทางQ>X>V>Mผ่านใบพัด Mสะท้อนให้เห็นถึงการที่แล้วดังนี้เส้นทางย้อนกลับของO O>Z>S>Sดังนั้นจะถูกแทนที่ด้วยAS

Input / Output

คุณผ่าน:

  1. รายการของ 3 rotors (เป็นจำนวนเต็ม)
  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

@coredump แก้ไข
Nathan Merrill

ฉันเข้าใจหรือไม่ว่าใบพัดทำงานยังไม่ถูกต้องหรือไม่?
J Atkin

คำตอบ:


4

Python 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เป็นตัวสะท้อนแสง

Ungolfed:

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'

ฉันคิดว่านี่ใช้งานได้ แต่ให้ผลลัพธ์ที่แตกต่างออกไปเนื่องจากสิ่งที่ (ฉันคิดว่า) เป็นจุดบกพร่องในการอ้างอิง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.