Python學習——Caesar Cipher密碼破解(加密)方法

Decoder17發表於2020-12-15

Caesar Cipher

前言

好久沒更新部落格了,今天我們來共同學習關於愷撒密碼(Caesar Cipher)專案。可能對大多數人來講,並不知道什麼是愷撒密碼,其實一開始我也不懂,也是查閱了相關資料才瞭解了什麼是Caesar Cipher,愷撒密碼說白了是字母密碼加密的一種方式,比如你用一段英文給對方傳送一則訊息,但是你又不想你的訊息被第三者知道,那麼就可以通過愷撒密碼進行傳遞,將你要傳遞的訊息字母在金鑰數字的加密下把正常的一則訊息變成一串“亂碼”,當然你的通訊物件是瞭解你們之間的“協議”(通訊金鑰數字)的。今天要講的專案就是通過程式來將訊息明文加密成密文,將密文破解成訊息明文。

一、愷撒密碼介紹

愷撒密碼的核心是凱撒密碼的金鑰,是 1 到 26 之間的一個數字。如果要破解密文就必須要知道這個金鑰(也就是知道用於加密訊息的數字),否則無法對這個保密的程式碼進行解密。
前面我們講到,愷撒密碼是用字母來傳遞,且要用到專門設定的金鑰,那麼具體傳遞方式是什麼樣的呢。
首先我們將要傳遞的訊息(用字母、數字、符號組成)寫下,並用一個
“移位後的”字母來代替它,移位個數就是前面我提到的金鑰。替換完成的新“訊息”(實則已經是亂碼)完全隱藏了我們要傳遞的訊息 內容。例如把字母 A 移動 3格,就會得到字母 D。如果把 A 移動兩格,就會得到字母 C。依次將所有的明文訊息碼通過“移位”變成沒有可讀性的密文。
如果以 3 作為一個金鑰來加密明文“Howdy”,則:
● 字母“H”變成了“K”;
● 字母“o”變成了“r”;
● 字母“w”變成了“z”;
● 字母“d”變成了“g”;
● 字母“y”變成了“b”。
祕文“Howdy”用 3 作為金鑰進行加密,變成了“Krzgb”。

二、ASCII 碼以及用數字表示字母

1.什麼是ASCII碼

ASCII碼(American Standard Code for Information Interchange,美國標準資訊交換程式碼)是一種程式碼,它將每個字元和 32 到 126 之間的一個數字進行關聯。大寫字母“A”到“Z”是 ASCII 數字 65 到 90。小寫字母“a”到“z”是 ASCII 數字97 到 122。數字“0”到“9”的 ACSII 數字是 48 到 57。表 15-1 展示了所有的 ASCII 字元和編碼。
現代計算機使用 UTF-8,而不是 ASCII。但是 UTF-8 向後相容 ASCII,所以 ASCII 字元的 UTF-8 編碼和 ASCII 的編碼是一樣的。
大蘇打在這裡插入圖片描述
因此,如果想要把“A”移動 3 格,需要像下面這樣做:
● 把“A”轉換成編碼(65);
● 65 加 3,得到 68;
● 把編碼 68 轉換回字母(“D”)。

2.函式chr()和ord()

函式 chr()(“character”的簡寫)接受一個整數形式的順序編碼,並且返回單個字元的字串。ord()函式接受單個字元的字串,並且返回整數形式的順序編碼。輸入如下程式碼:

>>ord('Y')
89
>>chr(89)
'Y'
>>chr(ord('Y'))
'Y'

這兩個函式主要用於對明文訊息的加密,以及將密文訊息的破解作用,具體怎麼工作,接下里我們將繼續講!

三、程式的設計

1.主體程式程式碼

加密明文的核心是先將明文的所有字母、數字、符號轉化為數字,主要通過chr()函式來實現,在將數字集(轉化後的明文訊息)加上金鑰數字(明文字母后移則對應密文字母表後面的字母,字母越靠後對應的ASCII碼數字越大,因此轉化後數字明文應當加上金鑰數字)。得到新的密文數字,再將密文數字通過ord()函式轉化為密文字母,得到的就是愷撒密碼了。整體的程式設計核心是這個思路!

# Caesar Cipher

def getTranslatedMessage(mode, message, key):
    if mode[0] == 'd':
        key = -key  # 如果是解密(d)工作模式,則金鑰為負數
    translated = ''  # 加(解)密生成的密(明)文

    for symbol in message:  # 遍歷密(明)文資訊
        if symbol.isalpha():  # 如果是字母
            num = ord(symbol)  # 獲取字母的ASCII碼,注意:ord()函式只能用於將字母轉化為ASCII碼的數字
            num += key  # 通過金鑰對密文進行移位操作從而獲得真實的明文字母
            if symbol.isupper():  # 所有密文字母是大寫
                if num > ord('Z'):
                    num -= 26
                elif num < ord('A'):
                    num += 26
            elif symbol.islower():
                if num > ord('z'):
                    num -= 26
                elif num < ord('a'):
                    num += 26

            translated += chr(num)
        else:
            translated += symbol
    return translated


mode = getMode()
message = getMessage()
key = getKey()

print('Your translated text is:')
print(getTranslatedMessage(mode, message, key))

2.模組分析

模式(加密、解密)選擇函式

def getMode():
    while True:
        print('Do you wish to encrypt or decrypt a message?')
        mode = input().lower()
        if mode in 'encrypt e decrypt d brute b'.split():
            return mode
        else:
            print('Enter either "encrypt" or "e" or "decrypt" or "d".')

說明:此函式主要供使用者選擇模式專用比較簡單,就是返回一個使用者輸入的選項(解密還是加密)。

加(解密)物件函式

def getMessage():
    print('Enter your message:')
    return input()

金鑰(數字)選擇函式

def getKey():
    key = 0
    while True:
        print('Enter the key number (1-%s)' % (MAX_KEY_SIZE))
        key = int(input())
        if (key >= 1 and key <= MAX_KEY_SIZE):
            return key

說明:這裡要要注意的金鑰數字的選擇範圍,金鑰數字為什麼只能是26以內的數字,由於英文字母只有26個,因此我們的“移位”範圍只能在26之內。這樣才能不至於使字母被替換成了其他符號!

總結

總的來講專案不是太難,比較簡單,而且涉及的函式不是特別多用到的Python方法也不多,都是常用的字串方法,很適合大家練練手。就程式本身而言,還有些不足,比如金鑰太少,在今天日益發達的網際網路時代,26個數字的金鑰太容易被破解了,只要將26個金鑰數字一個個帶入其中很容易破解密碼!
那麼接下里我們將就如何暴力破解再分析下!

延伸閱讀

我們在不知道金鑰數字的情況下,可以把26個數字一個個用來試總有一款能獲取到我們要的明文訊息,當然我們將這項繁瑣的工作交給計算機來處理。
既然是一個個的試金鑰,這時候我們想到Python的迴圈迭代可以幫我們處理這個工作。

print('Your translated text is:')
if mode[0] != 'b':
    key = getKey()
    print(getTranslatedMessage(mode, message, key))
else:
    for key in range(1, MAX_KEY_SIZE + 1):
        print(key, getTranslatedMessage('decrypt', message, key))

說明:首先我們將使用者輸入金鑰的方式改為for迴圈迭代的方式,當模式選擇為解密就將金鑰提供函式改為range()函式for迴圈迭代,這樣就可以將所有(26個數字)可能金鑰新增到主體程式中試,最後得到的結果可以很快找到訊息原始訊息明文。

愷撒密碼專案分享到此告一段落了。
——————————————
碼字不易。

希望每一期的分享對大家有所幫助,也感謝大家多多支援作者。

要想學習更多有關Python知識可以點選關注作者,或者評論區留言,我會不定期更新分享有關Python學習的知識,你們的每一次點贊收藏關注都是對作者最大的鼓勵。

相關文章