1. 程式人生 > >Python實現Enigma密碼機

Python實現Enigma密碼機

# -*- coding: utf-8 -*-
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()


這不是我最初寫的程式碼,之前寫的程式碼太醜,後來借鑑了別人的程式碼改進了一下。

enigma密碼機的原理網上有很多,這裡我就不重複了,enigma密碼在當時被認為不可破解主要是因為它使用了轉子這個部件實現加密一個字元變化一次替換表,當轉子數量大道一定程度,幾乎可以達到加密時不使用重複的替換表,使傳統的破解多表代替密碼的方式失效(找替換表加密週期)。

程式設計實現的主要難點在於轉子和反射器的設計。

在程式碼中轉子我用3個元素為0-25的數字組成的字元表示。陣列中每一個數字表示當前位置將對映到下一個轉子的位子,就像上圖中轉子中的連線。

反射器也是自動生成的陣列,需要注意的是必須必須保證對任意x,y (0<=x,y<=25)reflector[x]=y , reflector[y]=x 這樣才能保證密文的順利還原。

剛剛學Python,有很多地方寫不好,如有改進方法也請各位多多指教。