密碼學 - Playfair 密碼



Playfair 密碼,也稱為 Playfair 方格或 Wheatstone-Playfair 密碼,是一種手動對稱加密方案,是第一個使用文字二元組替換的方案。查爾斯·惠斯通於 1854 年建立了該技術,但它以萊爾德·普萊費爾的名字命名,以促進其使用。

這種方法加密的是字母對,而不是像簡單替換密碼和以前使用的更復雜的維吉尼亞密碼系統那樣加密單個字母。因此,Playfair 密碼更難破解,因為用於基本替換密碼的頻率分析不適用於它。二元組的頻率分析是可能的,但極其複雜。由於有 600 個可能的二元組,而不是 26 個可能的單字母組(單個符號,在此上下文中通常是字母),因此需要更大的密文才能發揮作用。

歷史

Playfair 密碼是第一個也是最著名的使用對稱加密的二元組替換密碼。查爾斯·惠斯通於 1854 年發明了這種密碼,萊爾德·普萊費爾倡導使用這種密碼,並以他的名字命名。與僅加密單個字母的傳統替換密碼不同,Playfair 密碼方法對二元組或字母片段進行編碼。

Playfair 密碼速度快,並且不需要任何其他工具即可操作。英國和澳大利亞軍隊在第一次世界大戰、第二次布林戰爭和第二次世界大戰期間戰術性地使用了它。加密的主要目的是在實際戰鬥中保護非關鍵但重要的資料。當敵方密碼分析員解密它時,這些資訊已毫無用處。

瞭解 Playfair 密碼

Playfair 密碼包含一個 5x5 的字母矩陣(金鑰表),沒有重複的字母。字母 I 和 J 被視為同一個字母。我們透過按順序排列關鍵字的唯一字母,然後是字母表的其餘字母來建立金鑰表。

以單詞 SECURITY 為例。首先,我們將該短語的字母記錄在 5x5 矩陣的第一個方格中 -

Playfair Cipher

然後,矩陣的其餘方格用字母表中剩餘的字母填充,按字母順序排列。但是,由於有 26 個字母,而只有 25 個方格可用,因此我們將 I 和 J 分配到同一個方格。

Playfair Cipher Understanding

在選擇術語時,請確保沒有字母重複,尤其是不應同時出現字母 I 和 J。例如,像 INJURE、JUICE 和 JIGSAW 這樣的關鍵字將被取消資格,因為它們同時包含 I 和 J,這違反了此標準。

加密過程

Playfair 密碼的加密過程包括將訊息轉換為其加密形式的若干步驟。

建立金鑰方格

首先,我們將使用指定的關鍵字建立一個金鑰方格。在本例中,我們將使用術語 SECURITY -

Playfair Cipher encryption

準備訊息

在加密訊息之前,我們必須先對其進行處理。我們將 J 視為 I,因此在加密過程中省略 J。我們還刪除任何非字母字元,例如空格和標點符號。

例如,處理字串 HELLOWORLD 得到 HELOWORLD。

配對字母

我們繼續將建立的訊息分成字母對(二元組)。如果二元組中兩個連續的字母相同,則在它們之間插入一個 X。此外,如果明文長度為奇數,我們會在末尾附加 X 以建立一個完整的二元組。

例如,在處理單詞“HELLO WORLD”時,我們將將其分成字母對 -

HE LL OW OR LD

二元組 LL 有相同的連續字母,因此我們在它們之間插入 X -

HE LX LO WO RL D

插入後訊息的長度不規則,因此我們在末尾附加 X 以使其長度為偶數 -

HE LX LO WO RL DX

加密規則

主要有三種標準用於加密同一對中的字母。

  • 如果對中的兩個字母在金鑰方格的同一行中,我們用它們右側的字母替換它們。

  • 如果對中的兩個字母都位於金鑰方格的同一列中,我們將用它們下方的字母替換每個字母。

  • 如果字母位於不同的行和列中,我們用它們形成一個矩形,並用相對角上的字母替換每個字母。

使用帶有關鍵字 SECURITY 的矩陣,讓我們找到每個對的行和列,並對 HELLOWORLD 應用加密規則,其對為 -

HE LX LO WO RL DX

將加密規則應用於所有字母對後,我們將得到 FUOQMPXNSPHQ。

解密過程

使用 Playfair 密碼解密加密的訊息時,該方法需要反轉加密過程中使用的操作。

金鑰方格構建

與加密過程一樣,解密方法首先使用關鍵字 SECURITY 建立金鑰方格。金鑰方格是幫助解密編碼訊息的關鍵參考網格。

此金鑰方格為在解密過程中理解加密文字奠定了基礎。

加密規則

解密規則只是加密規則的反向。當對中的兩個字母都在金鑰方格的同一行中時,我們用它們左側的字母替換它們。

同樣,假設對中的兩個字母都位於金鑰方格的同一列中。在這種情況下,我們將每個字母替換為其正上方的字母。當字母位於不同的行和列中時,我們使用字母對形成一個矩形,並用相對角上的字母替換每個字母。

過程

讓我們藉助上述解密規則解密訊息 FUOQMPXNSPHQ。因此,我們將逐一處理它們。

F 和 U 位於不同的行和列中,從而形成了一個以 E、U、F 和 H 為角的矩形。將 F 與其相對角 H 交換,將 U 與其相對角 E 交換,得到 HEOQMPXNSPHQ。

O 和 Q 位於不同的行和列中,從而形成了一個以 L、O、X 和 O 為角的矩形。將 O 與其相對角 L 交換,將 Q 與其相對角 X 交換,得到 HELXMPXNSPHQ。

繼續使用這種技術會產生HELXLOWORLDX。此時,我們擁有HELXLOWORLDX。去除X後,我們得到HELLOWORLD。

Playfair 密碼的重要性

在第一次和第二次世界大戰期間,由於 Playfair 密碼相較於當時其他密碼的相對複雜性,它獲得了普及。此外,資料加密和解密都不需要任何專門的裝置或方法。然而,隨著計算機的引入,Playfair 密碼變得過時,因為計算機可以輕鬆破解程式碼以解密 Playfair 密碼。

因此,隨著數字加密的改進和時間的推移,由於資料落入非預期人員手中的風險,Playfair 密碼不再是一種可接受的訊息編碼方法。因此,不建議企業使用 Playfair 密碼。

使用 Python 實現

Playfair 密碼使用原始文字(明文)中的字母對(二元組)進行操作。它使用一個 5x5 的金鑰方陣來加密這些二元組。金鑰方陣由一個關鍵字和英文字母表建立。在加密之前,明文轉換為小寫,空格被移除,雙字母由佔位符字母('x')分隔。然後將明文拆分為二元組。對於每個二元組,使用基於字母在金鑰方陣中位置的特定規則找到相應的加密二元組。然後將加密的二元組連線在一起,形成最終的加密訊息。金鑰和明文都可以更改,從而建立不同的加密選項。

示例

以下是 Playfair 密碼在 Python 中的實現:

# List of alphabets
alphabet_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

# Function to convert the string to lowercase
def to_lowercase(text):
   return text.lower()

# Function to remove all spaces in a string
def remove_spaces(text):
   new_text = ""
   for char in text:
      if char != " ":
         new_text += char
   return new_text

# Function to group 2 elements of a string
def group_characters(text):
   groups = []
   group_start = 0
   for i in range(2, len(text), 2):
      groups.append(text[group_start:i])
      group_start = i
   groups.append(text[group_start:])
   return groups

# Function to fill a letter in a string element
def fill_letter(text):
   k = len(text)
   if k % 2 == 0:
      for i in range(0, k, 2):
         if text[i] == text[i+1]:
            new_word = text[0:i+1] + str('x') + text[i+1:]
            new_word = fill_letter(new_word)
            break
         else:
            new_word = text
   else:
      for i in range(0, k-1, 2):
         if text[i] == text[i+1]:
            new_word = text[0:i+1] + str('x') + text[i+1:]
            new_word = fill_letter(new_word)
            break
         else:
            new_word = text
   return new_word

# Generating the 5x5 key square matrix
def generate_key_matrix(word, alphabet_list):
   key_letters = []
   for char in word:
      if char not in key_letters:
         key_letters.append(char)

   complementary_elements = []
   for char in key_letters:
      if char not in complementary_elements:
         complementary_elements.append(char)
   for char in alphabet_list:
      if char not in complementary_elements:
         complementary_elements.append(char)

   matrix = []
   while complementary_elements != []:
      matrix.append(complementary_elements[:5])
      complementary_elements = complementary_elements[5:]

   return matrix

# Searching for an element in the matrix
def search_element(matrix, element):
   for i in range(5):
      for j in range(5):
         if matrix[i][j] == element:
            return i, j

# Encryption using Row Rule
def encrypt_row_rule(matrix, e1_row, e1_column, e2_row, e2_column):
   char1 = ''
   if e1_column == 4:
      char1 = matrix[e1_row][0]
   else:
      char1 = matrix[e1_row][e1_column+1]

   char2 = ''
   if e2_column == 4:
      char2 = matrix[e2_row][0]
   else:
      char2 = matrix[e2_row][e2_column+1]

   return char1, char2

# Encryption using Column Rule
def encrypt_column_rule(matrix, e1_row, e1_column, e2_row, e2_column):
   char1 = ''
   if e1_row == 4:
      char1 = matrix[0][e1_column]
   else:
      char1 = matrix[e1_row+1][e1_column]

   char2 = ''
   if e2_row == 4:
      char2 = matrix[0][e2_column]
   else:
      char2 = matrix[e2_row+1][e2_column]

   return char1, char2

# Encryption using Rectangle Rule
def encrypt_rectangle_rule(matrix, e1_row, e1_column, e2_row, e2_column):
   char1 = matrix[e1_row][e2_column]
   char2 = matrix[e2_row][e1_column]

   return char1, char2

# Encrypting text using the Playfair Cipher
def encrypt_playfair_cipher(matrix, plaintext_list):
   cipher_text = []
   for i in range(0, len(plaintext_list)):
      char1 = 0
      char2 = 0
      ele1_x, ele1_y = search_element(matrix, plaintext_list[i][0])
      ele2_x, ele2_y = search_element(matrix, plaintext_list[i][1])

      if ele1_x == ele2_x:
         char1, char2 = encrypt_row_rule(matrix, ele1_x, ele1_y, ele2_x, ele2_y)
      elif ele1_y == ele2_y:
         char1, char2 = encrypt_column_rule(matrix, ele1_x, ele1_y, ele2_x, ele2_y)
      else:
         char1, char2 = encrypt_rectangle_rule(matrix, ele1_x, ele1_y, ele2_x, ele2_y)

      cipher = char1 + char2
      cipher_text.append(cipher)
   return cipher_text

# Main function
text_plain = 'tutorialspoint'
text_plain = remove_spaces(to_lowercase(text_plain))
plaintext_list = group_characters(fill_letter(text_plain))
if len(plaintext_list[-1]) != 2:
   plaintext_list[-1] = plaintext_list[-1]+'z'

key = "bestkey"
print("The Key text:", key)
key = to_lowercase(key)
matrix = generate_key_matrix(key, alphabet_list)

print("The Plain Text:", text_plain)
cipher_list = encrypt_playfair_cipher(matrix, plaintext_list)

cipher_text = ""
for i in cipher_list:
   cipher_text += i
print("The CipherText:", cipher_text)

以下是上述示例的輸出:

輸入/輸出

The Key text: bestkey
The Plain Text: tutorialspoint
The CipherText: bxeqpmdhcwphqb

優點

  • 如果我們仔細檢查演算法,我們可以看到該過程的每個階段都會產生唯一的密文,這使得密碼分析師更難破解。

  • 它對蠻力攻擊不敏感。

  • 密碼分析是不可能的(在不知道金鑰的情況下解碼密碼)。

  • 消除了簡單 Playfair 方陣密碼中的一個缺陷。

  • 替換操作很簡單。

缺點

Playfair 密碼存在以下缺點:

  • 僅支援 25 個字母。

  • 它與該數量的字元不相容。

  • 僅接受大寫和小寫字母。

  • 不允許使用空格、換行符和標點等特殊字元。

總結

Playfair 密碼被認為是最古老和最有效的資料加密方法之一。深入理解 Playfair 密碼是資料加密和機器學習的基礎。

廣告

© . All rights reserved.