Enigma模拟-Python

设计思想

Enigma机的机械结构:
  • 键盘:加密人员通过键盘进行输入

  • 转子:Enigma机上一般装有至少3个转轮。每个转轮有代表26个字母的触头和触点,触点和触头在转轮内部有导线相连(一个转轮相当于一组单表代替密码),同时外部有棘轮控制转动的幅度。当按动键盘上的单键时,最右边的转轮就会转动一次,每转动26次就会发生进位,带动下一个轮转动。每当转轮转动暂停下来,转轮的触头就会和下一个转轮的触点重新接触,构成通路,按动单键产生的电信号就会经过三个转轮(转轮的触头和下一个转轮的触点有26种接触可能,就是26种通路可能,也就是26张单表)。

  • 反射板:从最后一个转轮出来的电信号会经过反射板,反射板会对信号再次进行置换,接着反射回去,让其再次通过三个转轮,随后输出。

  • 显示板:输出的字母会在显示板上展现,随后会另有机器打印记录。

  • 连接板:设置在机器底部,可以将一对字母短接,相当于是单表加密。

实现的关键:
  • 转子作为单表代替密码,可采用随机代替的方式实现。
  • 反射器是设计关键,需要保证\(D(a) = b, \quad D(b) = a\),即\(D(D(x))=x\)。
  • 转子转动规则为26进1.

python实现

import random      
from copy import copy       
reflector=[18, 16, 12, 15, 19, 13, 23, 20, 9, 8, 21, 14, 2, 5, 11, 3, 1, 22, 0, 4, 7, 10, 17, 6, 25, 24]  
raw_cog=[[6, 10, 23, 9, 19, 2, 21, 1, 7, 24, 0, 17, 15, 3, 8, 4, 14, 12, 16, 25, 11, 18, 22, 20, 13, 5]  
,[0, 7, 1, 10, 19, 5, 9, 18, 4, 23, 2, 20, 15, 24, 22, 8, 12, 25, 6, 13, 3, 11, 21, 17, 16, 14]  
,[23, 2, 4, 13, 14, 21, 12, 0, 9, 16, 5, 17, 20, 22, 10, 24, 7, 3, 25, 8, 15, 6, 19, 18, 11, 1]]  
  
def shift(List,n):    
    return List[n:]+List[:n]    
  
class Cog:#模拟转子   
    def __init__(self,temp):    
        self.cog=copy(temp)      
    def rotate(self):     
        #self.cog=self.cog[1:]+self.cog[:1]      
        self.cog=shift(self.cog,1)      
    def printStatus(self):#输出转子当前的状态  
        for i in self.cog:  
            print i,  
    def nextNum(self,x):  
        return self.cog[x]  
    def lastNum(self,x):  
        return self.cog.index(x)  
  
class Enigma:  
    def __init__(self,cogSum):#cogSum是要使用的转子数  
        global reflector  
        self.lenCipher=0 #记录密文长度,计算转子转动  
        self.cogSum=cogSum  
        self.cogList=[] #所有使用的转子list  
        self.reflector=copy(reflector) #反射器  
        for i in range(0,cogSum):  
            self.cogList.append(Cog(raw_cog[i]))  
    def printStatus(self):#输出Enigma密码机当前的状态  
        for i in range(0,self.cogSum):  
            print 'cog'+str(self.cogSum)+': '  
            self.cogList[i].printStatus()  
            print  
        print 'reflector:',  
        for i in self.reflector:  
            print i,  
    def dealChar(self,c):#加密一个字符,并且转动转子  
        #加密字符  
        num=ord(c)-ord('a')  
        for i in range(0,self.cogSum):  
            num=self.cogList[i].nextNum(num)  
        num=self.reflector[num]  
        for i in range(self.cogSum-1,-1,-1):  
            num=self.cogList[i].lastNum(num)  
        #转动转子  
        for i in range(0,self.cogSum):  
            if 26**i<=self.lenCipher and self.lenCipher%26**i==0:  
                self.cogList[i].rotate()  
        return chr(ord('a')+num)  
    def encode(self,oriStr):#字符串的加密,只处理小写英文字母,忽略其他字符  
        ciphertext=''  
        oriStr=oriStr.lower()  
        for eachChar in oriStr:  
            if eachChar.isalpha():  
                self.lenCipher+=1  
                ciphertext+=self.dealChar(eachChar)  
        return ciphertext  
  
def main():  
    sumcog=input('请输入要使用的转子数目(最多3个):')  
    for i in range(0,sumcog):  
        print '请输入一个0-25的数字以确定第'+str(i+1)+'一个转子起始位置:'  
        c1=input()  
        raw_cog[i]=shift(raw_cog[i],c1) #调整转子的初始位子  
  
    rawString=raw_input('请输入要加密的字符串')  
    test=Enigma(sumcog)  
    temp=test.encode(rawString)  
    print temp  
  
if __name__ == '__main__':  
    main()

测试

屏幕快照 2017-03-27 下午9.53.53

输入相同字符串:aaaaa,加密后得到zjfns;
再次使用相同设置加密zjfns,得到原字符串aaaaa。

posted @ 2017-05-24 20:14  tino_ryj  阅读(1489)  评论(0编辑  收藏  举报