如何使用2个定制转子解密enigma并且没有反射器?

时间:2017-10-03 17:26:29

标签: encryption cryptography sage

TL; DR:因此,对于我们的加密类中的家庭作业,我们需要编写一个脚本来解密来自Enigma机器的给定密文,该机器具有两个给定的转子,没有反射器和一个键。

作业

字母是通常的英文字母[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q ,R,S,T,U,V,W,X,Y,Z]。

转子

λ 1 = [8,13,24,18,9,0,7,14,10,11,19,25,4,17,12,21,15,3, 22,2,20,16,23,1,6,5和

λ 2 = [10,2,21,18,23,6,16,14,8,11,1,25,15,20,0,24,17,19, 22,5,4,3,9,12,13,7]

K =< 1,13>

密文:XKWOU YTDLZ ZIFCY DBRWS FLGXV DUDNA KOFJA QHRKM NZWTY PZIJS ...(不会粘贴所有密文,因为明文可能不是英文版。)

我尝试了什么

根据我的理解,给定转子λ 1 λ 2 a i - 明文字母 p i 已加密为

c i -m 2 λ 2 ρ m 2 ρ -m 1 λ 1 ρ m 1 (p i

因此,解密将是相反的 p i -m 1 λ 1 -1 ρ m 1 ρ -m 2 λ 2 -1 ρ m 2 (c i

在哪里

i 是转子位置的字母索引< 0,0>

m 1 m 2 如此 i = m 1 + 26 m 2 + ... (如果 i = 9 = 9 + 26 * 0 ,然后 m 1 = 9,m 2 = 0 ,如果 i = 37 = 11 + 26 * 1 ,然后 m 1 = 11,m 2 = 1

ρα(t) 是一个旋转函数 ρα(t )= t +α(mod 26)

给出转子置换

λ(t) λ(t)=λ[t] (对于实例λ 1 ('e')=λ 1 [4] = 9 )。

λλ -1 < / sup>(t)= t (如果λ 1 (4)= 9,则λ 1 - 1 (9)= 4

代码部分

这是我试图在Sage中编写的脚本:

alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
rotor_1  = [8, 13, 24, 18, 9, 0, 7, 14, 10, 11, 19, 25, 4, 17, 12, 21, 15, 3, 22, 2, 20, 16, 23, 1, 6, 5]
rotor_2  = [10, 2, 21, 18, 23, 6, 16, 14, 8, 11, 1, 25, 15, 20, 0, 24, 17, 19, 22, 5, 4, 3, 9, 12, 13, 7]
cText = 'XKWOU YTDLZ ZIFCY DBRWS FLGXV DUDNA KOFJA QHRKM NZWTY PZIJS'
key = [1, 13]

def oppositeRot(rot):
    l=len(rot)
    oppositeRot=[0]*l
    for i in range(0,l):
        oppositeRot[rot[i]]=i
    return oppositeRot

def rotate(t, a):
    return alphabet[(alphabet.index(t) + a ) % len(alphabet)]

def rotor(t, rot):
    return alphabet[(alphabet.index(t) + rot[alphabet.index(t)]) % len(alphabet)]

def decipher(ciphertext, rot1, rot2, key):
    oppRot1 = oppositeRot(rot1)
    oppRot2 = oppositeRot(rot2)

    plaintext = "";
    m_1 = key[0]
    m_2 = key[1]
    for i in range (0, len(ciphertext)):
        if ciphertext[i] != ' ':
            c = alphabet[(alphabet.index(ciphertext[i]))] # c_i
            p = rotate(rotor(rotate(rotate(rotor(rotate(c, m_2), oppRot2), -m_2), m_1), oppRot1), -m_1) # p_i

            m_1 = (m_1 + 1) % len(oppRot1)

            if m_1 == 0:
                m_2 = (m_2 + 1) % len(oppRot2)

            plaintext += p
    return plaintext;

decipher(cText, rotor_1, rotor_2, key)

为什么这不起作用的任何建议/想法?我已经在这几个小时了,似乎无法发现我做错了什么。

1 个答案:

答案 0 :(得分:1)

我之前看过那个作业;)。 不确定您的代码有什么问题,但您可以检查我的解决方案。

alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

def numerify(text):
    res = []
    for letter in text:
        num = alphabet.index(letter)
        res.append(num)
    return res

def stringify(numbers):
    res = ''
    for number in numbers:
        letter = alphabet[number]
        res += letter
    return res

def rot(m, a):
    return (a+m) % len(alphabet)

def rsubst(rot, a):
    return rot.index(a)

def deEnigma(key, L1, L2, ciphertext):
    cipherVals = numerify(ciphertext)
    messageVals = []
    m1 = key[0]
    m2 = key[1]
    rIdx = 0

    for cipherVal in cipherVals:
        val = cipherVal
        val = rot(m2, val)
        val = rsubst(L2, val)
        val = rot(-m2, val)
        val = rot(m1, val)
        val = rsubst(L1, val)
        val = rot(-m1, val)

        m1 += 1
        rIdx += 1
        if (rIdx % len(alphabet)) == 0:
            m2 += 1

        messageVals.append(val)

    return stringify(messageVals)

只需将变量传递到deEnigma()

即可