返回文章列表

轉置密碼加密技術與Python實作

本文深入解析轉置密碼的加密原理,並提供 Python 程式碼實作。轉置密碼透過重新排列明文字元順序達到加密目的,理解其原理有助於提升程式設計能力和資訊安全意識。文章涵蓋了密碼學基本概念、Python 列表操作、變數作用域等相關知識,適合對資訊安全和 Python 程式設計有興趣的讀者。

資安 Python

轉置密碼是一種透過重新排列明文字元順序來達到加密效果的技術,常用於資訊安全領域。其核心概念是利用金鑰決定明文重新排列的規則,例如將明文填入表格後,再以不同的順序讀取字元來產生密鑰。瞭解轉置密碼的原理和實作方式,有助於提升程式設計能力和資訊安全意識。本文除了講解轉置密碼的加密原理外,也示範如何使用 Python 程式碼實作轉置加密演算法,其中包含列表操作、變數作用域等 Python 基礎知識的應用。透過實際操作範例,讀者能更深入理解轉置密碼的運作機制,並學習如何運用 Python 進行加密演算法的開發。

轉置密碼(Transposition Cipher)加密技術解析

轉置密碼是一種常見的加密技術,主要透過重新排列明文的字元順序來達到加密的目的。本章節將探討轉置密碼的加密原理,並分析相關的程式實作。

轉置密碼加密原理

轉置密碼的核心思想是將明文按照一定的規則重新排列,形成密鑰。以下為具體步驟:

  1. 計算字元數量和金鑰:首先,計算明文的字元數量和所使用的金鑰。
  2. 繪製方格:根據金鑰的值,繪製相應數量的方格。例如,若金鑰為8,則繪製8個方格。
  3. 填寫明文:從左到右將明文填入方格中,若方格填滿,則繼續在下一行填寫。
  4. 遮蔽未使用的方格:在最後一行,若有未使用的方格,則將其遮蔽。
  5. 讀取密鑰:從第一列開始,從上到下讀取字元,形成密鑰。若到達列底,則移至下一列。

例項示範

假設明文為 “Common sense is not so common.",金鑰為8。首先,計算明文的字元數量(包含空格和標點符號)為30。

  1. 繪製8個方格,並填寫明文:

    C o m m o n (s) s
    e n s e (s) i s (s)
    n o t (s) s o (s) c
    o m m o n .
    
  2. 遮蔽最後一行的未使用方格。

  3. 從第一列開始讀取字元,形成密鑰:“Cenoonommstmme oo snnio. s s c”。

轉置密碼加密程式實作

以下為使用Python實作的轉置密碼加密程式:

# Transposition Cipher Encryption

import pyperclip

def main():
    myMessage = 'Common sense is not so common.'
    myKey = 8
    ciphertext = encryptMessage(myKey, myMessage)
    print(ciphertext + '|')  # 新增 | 字元以標示結尾
    pyperclip.copy(ciphertext)

def encryptMessage(key, message):
    ciphertext = [''] * key
    for col in range(key):
        pointer = col
        while pointer < len(message):
            ciphertext[col] += message[pointer]
            pointer += key
    return ''.join(ciphertext)

if __name__ == '__main__':
    main()

程式碼解析

  1. encryptMessage 函式

    • 初始化一個列表 ciphertext,包含 key 個空字串。
    • 遍歷每個列,並將對應的字元新增到 ciphertext 中。
    • 傳回拼接後的 ciphertext 字串。
  2. main 函式

    • 設定明文和金鑰。
    • 呼叫 encryptMessage 函式進行加密。
    • 輸出密鑰,並複製到剪貼簿。

#### 內容解密:

  1. encryptMessage 函式作用:此函式負責將明文根據指定的金鑰進行轉置加密,將明文字元重新排列成密鑰。
  2. ciphertext 初始化邏輯:使用列表推導式初始化 ciphertext 為包含 key 個空字串的列表,用於存放每一列的字元。
  3. pointer 變數作用:用於遍歷明文字元,每次遞增 key 以跳到下一行對應列的字元。
  4. ''.join(ciphertext) 邏輯:將 ciphertext 列表中的字串拼接成一個完整的密鑰字串傳回。
  5. main 函式流程:設定測試資料(明文和金鑰),呼叫加密函式進行加密,並輸出和複製密鑰結果。

函式與引數:深入理解Python程式設計

在Python程式設計中,函式是組織程式碼、提高重用性和降低複雜度的基礎元件。函式透過封裝特定的邏輯或運算,提供了一個可重複使用的程式碼區塊。本章節將詳細探討函式的定義、引數的傳遞以及函式內部的運作機制。

函式的基本概念

函式是透過def關鍵字定義的程式碼區塊。例如,在helloFunction.py中,我們定義了一個名為hello()的函式:

def hello():
    print('Hello!')
    print('42 plus 1 is', 42 + 1)

內容解密:

  • def hello(): 定義了一個名為hello的函式,該函式不接受任何引數。
  • print('Hello!')print('42 plus 1 is', 42 + 1) 是函式內部的兩條陳述式,分別輸出字串和計算結果。

當程式執行到hello()的呼叫時,控制權轉移到函式內部,執行其中的陳述式。完成後,控制權傳回呼叫處,繼續執行後續的陳述式。

引數的傳遞

transpositionEncrypt.py中,我們看到一個帶引數的函式定義:

def encryptMessage(key, message):
    # 加密邏輯

內容解密:

  • keymessage 是函式encryptMessage的兩個引數,分別代表加密的金鑰和待加密的訊息。
  • 呼叫該函式時,需要提供兩個引數,例如:encryptMessage(myKey, myMessage)

引數(parameter)和引數(argument)是兩個相關但不同的概念。引數是函式定義時使用的變數名稱,而引數是呼叫函式時傳遞給函式的值。

引數值的變化

考慮以下範例:

def func(param):
    param = 42
spam = 'Hello'
func(spam)
print(spam)

內容解密:

  • func(param) 定義了一個接受一個引數的函式,並在內部將該引數指定為42。
  • spam = 'Hello' 初始化了一個變數spam,其值為’Hello’。
  • func(spam) 呼叫了func函式,並將spam作為引數傳遞給它。
  • print(spam) 輸出了spam的值。

執行上述程式碼後,輸出仍為’Hello’,而不是42。這是因為在Python中,函式內部對引數的修改不會影響到外部傳入的變數,除非該變數是可變型別(如列表)並且被修改。

main()函式的作用

在許多Python程式中,特別是在本文的範例中,程式的進入點是main()函式。這種做法有助於組織程式碼,使其更具可讀性和可維護性。

def main():
    myMessage = 'Common sense is not so common.'
    myKey = 8
    ciphertext = encryptMessage(myKey, myMessage)
    print(ciphertext + '|')
    pyperclip.copy(ciphertext)

內容解密:

  • main() 定義了程式的主要邏輯,包括初始化變數、呼叫加密函式以及輸出和複製加密後的訊息。
  • 程式透過呼叫main()開始執行。

這種結構使得程式的邏輯更加清晰,也便於未來擴充和修改。

變數作用域與清單資料型態

在探討函式與變數時,我們經常會遇到一個重要的概念:變數作用域。變數作用域決定了變數的可見性和存取性。

區域變數與全域變數

每當函式被呼叫時,Python會為該函式建立一個區域作用域。區域作用域內的變數只在該函式內有效。當函式執行完畢後,區域作用域被銷毀,相關變數也被遺忘。

全域變數則是在所有函式之外定義的變數,它們在程式的任何地方都可被存取,直到程式結束時才會被銷毀。

範例程式碼:scope.py

spam = 42

def eggs():
    spam = 99  # 這裡的 spam 是區域變數
    print('在 eggs() 中:', spam)

def ham():
    print('在 ham() 中:', spam)  # 這裡的 spam 是全域變數

def bacon():
    global spam  # 明確指出 spam 是全域變數
    print('在 bacon() 中:', spam)
    spam = 0

def crash():
    print(spam)  # 這裡的 spam 是區域變數,但尚未指定
    spam = 0

print(spam)
eggs()
print(spam)
ham()
print(spam)
bacon()
print(spam)
crash()

程式碼解析

  1. 全域變數 spam:在函式外定義,初始值為 42。
  2. eggs() 函式:在函式內指定 spam = 99,此時的 spam 是區域變數,不影響全域變數 spam
  3. ham() 函式:未對 spam 指定,因此使用的是全域變數 spam
  4. bacon() 函式:使用 global 陳述式明確指出 spam 是全域變數,並將其值修改為 0。
  5. crash() 函式:嘗試在指定前列印 spam,由於此時的 spam 是區域變數且尚未指定,導致程式當機,錯誤訊息為 UnboundLocalError: local variable 'spam' referenced before assignment

清單資料型態

清單是一種可以包含多個值的資料型態。清單以方括號 [] 表示,元素之間以逗號分隔。

範例程式碼:transpositionEncrypt.py

key = 3
ciphertext = [''] * key  # 建立一個包含 key 個空字串的清單

清單特性

  • 可變性:清單是可變的,可以動態修改其內容。
  • 索引存取:可以透過索引來存取清單中的元素。
  • 多樣性:清單可以包含不同型別的元素,如字串、整數、浮點數等。

重點整理

  • 變數作用域:理解區域變數與全域變數的區別和使用場景。
  • global 陳述式:用於在函式內修改全域變數。
  • 清單資料型態:用於儲存多個值的集合,具備可變性和多樣性。

Python 中的列表(List)詳解

在 Python 程式設計中,列表(List)是一種非常重要且常用的資料結構,用於儲存多個值。本章節將探討列表的基本操作、特性及其與字串(String)的相似之處。

列表的基本定義與使用

列表是一種有序的集合,可以包含多個不同型別的元素,如字串、整數、浮點數,甚至是其他列表。以下是一個簡單的例子:

animals = ['aardvark', 'anteater', 'antelope', 'albert']
print(animals)  # 輸出:['aardvark', 'anteater', 'antelope', 'albert']

內容解密:

在這個例子中,animals 是一個列表變數,包含了四個字串元素。列表中的每個元素都稱為專案(Item)。使用 print(animals) 可以輸出整個列表。

索引(Indexing)與切片(Slicing)

列表支援索引和切片操作,這與字串的操作類別似。索參照於存取列表中的特定元素,而切片則用於取得列表的一部分。

animals = ['aardvark', 'anteater', 'antelope', 'albert']
print(animals[0])    # 輸出:'aardvark'
print(animals[1:3])  # 輸出:['anteater', 'antelope']

內容解密:

在上述程式碼中,animals[0] 傳回列表的第一個元素 'aardvark'animals[1:3] 則傳回從索引 1 到 3(不包含 3)的元素,即 ['anteater', 'antelope']

使用 for 迴圈迭代列表

for 迴圈可以用來遍歷列表中的每個元素,就像遍歷字串中的每個字元一樣。

for spam in ['aardvark', 'anteater', 'antelope', 'albert']:
    print('For dinner we are cooking ' + spam)

內容解密:

這段程式碼會逐一輸出列表中的每個元素,並將其與字串 'For dinner we are cooking ' 連線後列印出來。

將範圍物件(Range Object)轉換為列表

使用 list() 函式,可以將範圍物件轉換為列表。這對於需要產生一系列連續整數的場合非常有用。

myList = list(range(10))
print(myList)  # 輸出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

內容解密:

range(10) 生成一個包含從 0 到 9 的整數的範圍物件,list() 將其轉換為一個列表。

修改列表中的元素

與字串不同,列表中的元素是可以被修改的。

animals = ['aardvark', 'anteater', 'antelope', 'albert']
animals[2] = 9999
print(animals)  # 輸出:['aardvark', 'anteater', 9999, 'albert']

內容解密:

這裡將 animals 列表中索引為 2 的元素修改為 9999

列表的串接與重複

列表支援使用 +* 運算元進行串接和重複操作。

print(['hello'] + ['world'])  # 輸出:['hello', 'world']
print(['hello'] * 5)          # 輸出:['hello', 'hello', 'hello', 'hello', 'hello']

內容解密:

+ 用於串接兩個列表,而 * 用於將一個列表重複指定的次數。

使用 len()in 運算元

len() 函式可以用來取得列表的長度,而 in 運算元則用於檢查某個值是否存在於列表中。

animals = ['aardvark', 'anteater', 'antelope', 'albert']
print(len(animals))          # 輸出:4
print('anteater' in animals) # 輸出:True

內容解密:

len(animals) 傳回列表 animals 中的元素個數。'anteater' in animals 檢查 'anteater' 是否存在於 animals 中,並傳回 TrueFalse

轉置加密演算法詳解

轉置加密是一種常見的加密技術,透過重新排列明文的字元來實作加密。本章節將探討轉置加密的實作細節,並使用 Python 實作加密演算法。

轉置加密的基本原理

轉置加密的核心思想是將明文按照一定的規則重新排列,形成密鑰。假設我們要加密的字串是 'Common sense is not so common.',並使用金鑰 8。如果我們使用紙筆來模擬加密過程,可以將字串填入一個表格中,如下所示:

01234567
Common(s)s
ense(s)is(s)
not(s)so(s)c
ommon.

填入表格後,我們按照欄位順序讀取字元,形成密鑰。第一欄的字元索引為 081624,對應的字元為 'C''e''n''o'。按照此規則,我們可以得到密鑰。

Python 實作轉置加密

def transposition_encrypt(message, key):
    # 建立一個包含 key 個空白字串的列表
    ciphertext = [''] * key
    
    # 遍歷每個欄位
    for col in range(key):
        pointer = col
        
        # 將字元加入對應的欄位
        while pointer < len(message):
            ciphertext[col] += message[pointer]
            pointer += key
    
    # 合併所有欄位形成密鑰
    return ''.join(ciphertext)

message = 'Common sense is not so common.'
key = 8
encrypted_message = transposition_encrypt(message, key)
print(encrypted_message)

程式碼解析:

  1. 首先,我們建立一個包含 key 個空白字串的列表 ciphertext,用於存放每個欄位的字元。
  2. 遍歷每個欄位,使用 pointer 變數作為索引,將字元加入對應的欄位。
  3. 使用 while 迴圈將字元加入對應的欄位,直到 pointer 超出字串長度。
  4. 最後,將所有欄位的字符合併形成密鑰。

使用擴充指定運算元

在 Python 中,我們可以使用擴充指定運算元(如 +=)來簡化程式碼。例如:

spam = 40
spam += 2
print(spam)  # 輸出:42

spam = 'Hello'
spam += ' world!'
print(spam)  # 輸出:Hello world!

這種寫法可以簡化程式碼,提高可讀性。