密码学 - 一次性密码本密码的实现



在上一章中,我们了解了一次性密码本密码是什么,它是如何工作的以及它的优缺点。因此,在本章中,我们将了解如何使用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
广告