エニグママシンを実装する


18

Enigmaマシンは、ドイツ人などがメッセージを暗号化するために使用するかなり複雑な暗号マシンです。このマシンを実装するのはあなたの仕事です*。

ステップ1、回転

エニグママシンには、ローター用に3つのスロットがあり、これらの各スロットに5つの使用可能なローターがあります。各ローターには、26の異なる位置(AZ)があります。各ローターには、事前定義されたノッチ位置があります。

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

キーを押すと、次の手順が発生します。

  1. スロット1のローターが回転します
  2. スロット1のローターがノッチを通過すると、スロット2のローターが回転します。
  3. スロット2のローターがそのノッチにある場合(ただし、そこに移動しただけではない場合)、ローター2と3の両方が1回転します。

私たちはローター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、それは代入しEA

スロットには、すべての位置にあるローター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
これは、エニグマI、M3、M4で使用される暗号化アルゴリズムの正しい実装です。すべての設定は、プラグボードとUHRスイッチ仕事存在しているだけでなく:https://github.com/arduinoenigma/ArduinoEnigmaEngineAndUhrこれはで使用したのと同じ暗号化エンジンであるArduinoのエニグマ機シミュレータ

私は理解していると思いますが、正しく機能していないようです。以下にgist.github.com/JJ-Atkinson/ddd3896fe10d85b3b584を説明する要点を示します。
Jアトキン

最初の例では、「ローター1、3、5を使用している場合」と言いましたが、これはローター1、2、5(または最後のローター)になると思います。
コアダンプ

@coredump修正
ネイサンメリル

ローターがどのように機能するかについての私の理解はまだ間違っていますか?
Jアトキン

回答:


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、リフレクターです。

ゴルフをしていない:

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.