密碼學 - 一次性密碼本密碼的實現



在上一章中,我們瞭解了一次性密碼本密碼是什麼,它是如何工作的以及它的優缺點。因此,在本章中,我們將瞭解如何使用Python、Java和C++實現一次性密碼本密碼。

Python 實現

這個問題可以使用不同的方法解決,例如:

  • 使用模運算

  • 使用 XOR 運算

  • 使用 Python 的 onetimepad 模組

  • 使用 random、string 和 sqlite3 模組

因此,我們將在下面的章節中深入討論每種方法。

使用模運算

在程式碼中,模運算子 (%) 確保生成的字母保持在英文大寫字母的範圍內(ASCII 值從 65 到 90)。以下是它在加密和解密中使用方法的細分:

加密 - 對於訊息中的每個字元和金鑰中的相應字元,將它們的 ASCII 值相加。然後將總和除以 26 並保留餘數(使用模運算)。這確保它落在 0 到 25 的範圍內。新增 65 將其恢復到大寫字母的 ASCII 值範圍(65 到 90)。最後,使用 chr() 函式將生成的 ASCII 值轉換回其對應的字元。

解密 - 與加密類似,將相應訊息和金鑰字元的 ASCII 值相加。同樣,使用模 26 來確保總和落在 0 到 25 的範圍內。要解密,從這個總和中減去 26,並將結果用於使用 chr() 獲取對應的字元。

示例

以下是使用模運算的 Python 一次性密碼本密碼實現。

def otp_encrypt(message, key):
   encrypted_message = ""
   for i in range(len(message)):
      char = chr((ord(message[i]) + ord(key[i])) % 26 + 65)
      encrypted_message += char
   return encrypted_message

def otp_decrypt(encrypted_message, key):
   decrypted_message = ""
   for i in range(len(encrypted_message)):
      char = chr((ord(encrypted_message[i]) - ord(key[i])) % 26 + 65)
      decrypted_message += char
   return decrypted_message

# plaintext and key
message = "HELLO"
key = "WORLD"

encrypted_message = otp_encrypt(message, key)
print("Encrypted message:", encrypted_message)

decrypted_message = otp_decrypt(encrypted_message, key)
print("Decrypted message:", decrypted_message)

以下是上述示例的輸出:

輸入/輸出

Encrypted message: DSCWR
Decrypted message: HELLO

使用 XOR 運算

使用 XOR 運算,程式碼確保以一種使從僅加密文字中獲取原始訊息或金鑰非常困難的方式建立和解密加密字元。XOR(異或)是一種按位運算,它使用其輸入的位來獲取結果。當使用同一個值兩次進行 XOR 運算時,會得到原始值。這使得 XOR 成為一次性密碼本方法中加密的良好選擇。

示例

檢視下面的 Python 程式,瞭解使用 XOR 運算的一次性密碼本密碼:

def otp_encrypt(message, key):
   encrypted_message = ""
   for i in range(len(message)):
      char = chr(ord(message[i]) ^ ord(key[i]))
      encrypted_message += char
   return encrypted_message

def otp_decrypt(encrypted_message, key):
   decrypted_message = ""
   for i in range(len(encrypted_message)):
      char = chr(ord(encrypted_message[i]) ^ ord(key[i]))
      decrypted_message += char
   return decrypted_message

# plaintext and key
message = "HELLO"
key = "WORLD"

encrypted_message = otp_encrypt(message, key)
print("Encrypted message:", encrypted_message)

decrypted_message = otp_decrypt(encrypted_message, key)
print("Decrypted message:", decrypted_message)

以下是上述示例的輸出:

輸入/輸出
Encrypted message: DSCWR
Decrypted message: HELLO

使用 Python 的 onetimepad 模組

為了使用一次性密碼本方法加密和解密訊息,我們使用 onetimepad 模組。它提供加密和解密功能。此模組透過提供可隨時使用的一次性密碼本操作函式來簡化流程。只需幾行程式碼,您就可以輕鬆地加密和解密訊息。

示例

檢視下面使用 Python 的 onetimepad 模組的一次性密碼本密碼程式碼:

import onetimepad

def otp_encrypt(message, key):
   encrypted_message = onetimepad.encrypt(message, key)
   return encrypted_message

def otp_decrypt(encrypted_message, key):
   decrypted_message = onetimepad.decrypt(encrypted_message, key)
   return decrypted_message

# plain text and key
message = "This is a secret message"
key = "My key"

encrypted_message = otp_encrypt(message, key)
print("Encrypted message:", encrypted_message)

decrypted_message = otp_decrypt(encrypted_message, key)
print("Decrypted message:", decrypted_message)

以下是上述示例的輸出:

輸入/輸出
Encrypted message: 1911491845103e59414b161c2e0b451f4514280a530a021c
Decrypted message: This is a secret message

使用 random、string 和 sqlite3 模組

此 Python 程式碼實現了一個簡單的命令列工具,用於使用一次性密碼本密碼技術建立和管理加密訊息。此程式碼設定了處理加密訊息的基礎知識。它使用一次性密碼本密碼技術,並展示瞭如何生成金鑰、加密訊息以及解密它們。

在這個實現中,我們將使用 random、string 和 sqlite3 模組。這些模組在 Python 程式設計中用途廣泛,廣泛用於從基本的字串操作到資料庫管理和隨機資料生成的各種任務。

示例

檢視下面的 Python 程式:

import random
import string
import sqlite3

PUNC = string.punctuation
ALPHABET = string.ascii_letters

def initialize():
   connection = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False)
   cursor = connection.cursor()
   cursor.execute(
      "CREATE TABLE used_keys ("
         "id INTEGER PRIMARY KEY AUTOINCREMENT,"
         "key TEXT"
      ")"
   )
   return cursor

def create_key(_string, db_cursor):
   """
   Create the key from a provided string
   """
   retval = ""
   set_string = ""
   used_keys = db_cursor.execute("SELECT key FROM used_keys").fetchall()
   id_number = len(used_keys) + 1
   for c in _string:
      if c in PUNC or c.isspace():
         continue
      set_string += c
   key_length = len(set_string)
   acceptable_key_characters = string.ascii_letters
   for _ in range(key_length):
      retval += random.choice(acceptable_key_characters)
   if retval not in [key[0] for key in used_keys]:
      db_cursor.execute("INSERT INTO used_keys(id, key) VALUES (?, ?)", (id_number, retval))
      return retval, set_string
   else:
      return create_key(_string, db_cursor)

def encode_cipher(_string, key):
   """
   Encode the string using a generated unique key
   """
   retval = ""
   for k, v in zip(_string, key):
      c_index = ALPHABET.index(k)
      key_index = ALPHABET.index(v)
      cipher_index = (c_index + key_index) % 52
      retval += ALPHABET[cipher_index]
   return retval

def decode_cipher(encoded, key):

   # Decode the encoded string 
   retval = ""
   for k, v in zip(encoded, key):
      c_index = ALPHABET.index(k)
      key_index = ALPHABET.index(v)
      decode = (c_index - key_index) % 52
      retval += ALPHABET[decode]
   return retval

def main():
   # Main function
   exited = False
   choices = {"1": "Show keys", "2": "Create new key", "3": "Decode a cipher", "4": "Exit"}
   cursor = initialize()
   separator = "-" * 35
   print("Database initialized, what would you like to do:")
   try:
      while not exited:
         for item in sorted(choices.keys()):
            print("[{}] {}".format(item, choices[item]))
         choice = input(">> ")
         if choice == "1":
            keys = cursor.execute("SELECT key FROM used_keys")
            print(separator)
            for key in keys.fetchall():
               print(key[0])
            print(separator)
         elif choice == "2":
            phrase = input("Enter your secret phrase: ")
            key, set_string = create_key(phrase, cursor)
            encoded = encode_cipher(set_string, key)
            print(separator)
            print("Encoded message: '{}'".format(encoded))
            print(separator)
         elif choice == "3":
            encoded_cipher = input("Enter an encoded cipher: ")
            encode_key = input("Enter the cipher key: ")
            decoded = decode_cipher(encoded_cipher, encode_key)
            print(separator)
            print("Decoded message: '{}'".format(decoded))
            print(separator)
         elif choice == "4":
            print("Database destroyed")
            exited = True
   except KeyboardInterrupt:
      print("Database has been destroyed")

if __name__ == "__main__":
   main()

以下是上述示例的輸出:

輸入/輸出

OTP output

Java 實現

現在我們將藉助 Java 實現一次性密碼本密碼。在其中,我們將建立一個 OTP 類,並在類中包含三個函式:一個用於加密訊息,第二個用於解密訊息,第三個將是主方法。

在 encryptMessage() 函式中,我們將有兩個引數:明文和金鑰。因此,我們將使用 StringBuilder 來初始化密文的儲存。

計算金鑰長度後,我們將遍歷每個明文字元。然後,我們將新增相應的金鑰字元並應用模 128 用於 ASCII 範圍。之後,我們將加密字元附加到密文 StringBuilder。在 decryptMessage() 函式中反轉 encryptMessage() 函式的過程。

示例

以下是使用 Java 的一次性密碼本密碼的實現:

public class OneTimePad {

   // Encryption function to encrypt the given message
   public static String encryptMessage(String plaintext, String key) {
      StringBuilder ciphertext = new StringBuilder();
      int keyLength = key.length();
      for (int i = 0; i < plaintext.length(); i++) {
         char encryptedChar = (char) ((plaintext.charAt(i) + key.charAt(i % keyLength)) % 128);
         ciphertext.append(encryptedChar);
      }
      return ciphertext.toString();
   }

   // Decryption function to decrypt the message
   public static String decryptMessage(String ciphertext, String key) {
      StringBuilder plaintext = new StringBuilder();
      int keyLength = key.length();
      for (int i = 0; i < ciphertext.length(); i++) {
         char decryptedChar = (char) ((ciphertext.charAt(i) - key.charAt(i % keyLength) + 128) % 128);
         plaintext.append(decryptedChar);
      }
      return plaintext.toString();
   }

   public static void main(String[] args) {
      String plaintext = "Welcome to our Website";
      String key = "Secret";

      // Repeat the key if it's shorter than the plaintext
      while (key.length() < plaintext.length()) {
         key += key;
      }

      // Encryption
      String et = encryptMessage(plaintext, key);
      System.out.println("The Encrypted Text: " + et);

      // Decryption
      String dt = decryptMessage(et, key);
      System.out.println("The Decrypted Text: " + dt);
   }
}

以下是上述示例的輸出:

輸入/輸出

The Encrypted Text: *JOUTa8 Wa cHW IJVFNWW
The Decrypted Text: Welcome to our Website

C++ 實現

現在,我們將藉助 C++ 程式語言實現一次性密碼本密碼。此程式碼展示了使用 C++ 中的一次性密碼本密碼加密和解密訊息。定義並使用了兩個不同的函式,一個用於加密,一個用於解密,以及一個說明其應用的主函式。

示例

以下是使用 C++ 的一次性密碼本密碼的實現:

#include <iostream>
#include <string>

using namespace std;

// Encryption function to encrypt the message
string encryptMessage(string plaintext, string key) {
   string ciphertext = "";
   for (int i = 0; i < plaintext.length(); i++) {
      char encryptedChar = (plaintext[i] + key[i]) % 128;
      ciphertext += encryptedChar;
   }
   return ciphertext;
}

// Decryption function to decrypt the message
string decryptMessage(string ciphertext, string key) {
   string plaintext = "";
   for (int i = 0; i < ciphertext.length(); i++) {
      char decryptedChar = (ciphertext[i] - key[i] + 128) % 128;
      plaintext += decryptedChar;
   }
   return plaintext;
}

int main() {
   string plaintext = "Hello This is Tutorialspoint";
   string key = "Secret";

   // Encryption
   string et = encryptMessage(plaintext, key);
   cout << "The Encrypted Text: " << et << endl;

   // Decryption
   string dt = decryptMessage(et, key);
   cout << "The Decrypted Text: " << dt << endl;

   return 0;
}

以下是上述示例的輸出:

輸入/輸出

The Encrypted Text: O^T Th!F=qr TuTmlialsp int
The Decrypted Text: Hello Th|}qr Tutorialspoint
廣告
© . All rights reserved.