[Java] ハッシュ テーブルに基づくランダム文字置換暗号化アルゴリズム
1. はじめに
1.1 背景
現代社会では、情報の伝達と機密性が特に重要です。データのセキュリティを確保するために、さまざまな暗号化アルゴリズムを使用して情報を暗号化することがよくあります。しかし、従来の暗号化アルゴリズムが攻撃者によって解読されるリスクも高まっています。したがって、より安全な暗号化アルゴリズムを開発することが非常に重要です。
1.2 目的
この記事の目的は、ハッシュ テーブルに基づく単純な暗号化アルゴリズムを紹介することですが、このアルゴリズムは高い安全性と実用性を備えている必要があると思います。この記事では、アルゴリズムの設計と実装について詳しく説明します。
2. アルゴリズム設計
2.1 HashTableCreatorクラス
このアルゴリズムでは、まずマッピング関係を保存するハッシュ テーブルを作成する必要があります。HashTableCreator クラスは、ハッシュ テーブルを作成するために使用されます。ハッシュ テーブルには、26 個の文字、10 個の数字、およびスペース、合計 37 文字を保存できます。文字ごとに、1771 個の異なる文字のリストをランダムに生成し、そのリストと文字をハッシュ テーブルにマッピングします。
2.2 MessageEncryptor クラス
MessageEncryptor クラスは、メッセージの暗号化と復号化に使用されます。このクラスは、ハッシュ テーブルから各入力文字に対応するランダムな文字を取得し、それらを組み合わせて暗号化された文字列を作成します。メッセージを復号するには、暗号化された文字をハッシュ テーブル内の値と比較し、それがどの文字を表しているかを判断する必要があります。
3. アルゴリズムの実装
3.1 HashTableCreatorクラスの実装
このクラスは、HashMap を使用してハッシュ テーブルを保存し、Random クラスを使用してランダムな文字を生成します。このループでは、文字ごとに 1771 個の異なる文字のリストを生成し、ObjectOutputStream クラスを使用してハッシュ テーブルをファイルに書き込みます。
コード部分は次のとおりです。
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.*;
public class HashTableCreator {
public static void main(String[] args) {
Map<Character, List<Character>> hashTable = new HashMap<>();
int numChars = 1771;
Random rand = new Random();
Set<Character> existingChars = new HashSet<>();
for (char c = 'a'; c <= 'z'; c++) {
List<Character> charList = new ArrayList<>();
for (int i = 0; i < numChars; i++) {
char randChar;
do {
randChar = (char) (rand.nextInt(65535));
//随机取unicode编码字符
} while (existingChars.contains(randChar));
charList.add(randChar);
existingChars.add(randChar);
}
hashTable.put(c, charList);
}
for (char c = '0'; c <= '9'; c++) {
List<Character> charList = new ArrayList<>();
for (int i = 0; i < numChars; i++) {
char randChar;
do {
randChar = (char) (rand.nextInt(65535));
} while (existingChars.contains(randChar));
charList.add(randChar);
existingChars.add(randChar);
}
hashTable.put(c, charList);
}
List<Character> spaceList = new ArrayList<>();
for (int i = 0; i < numChars; i++) {
char randChar;
do {
randChar = (char) (rand.nextInt(65535));
} while (existingChars.contains(randChar));
spaceList.add(randChar);
existingChars.add(randChar);
}
hashTable.put(' ', spaceList);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hashtable.ser"))) {
oos.writeObject(hashTable);
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.2 MessageEncryptor クラスの実装
このクラスでは、ObjectInputStream クラスを使用してファイルからハッシュ テーブルを読み取ります。次に、Scanner クラスを使用して、暗号化するメッセージを標準入力から読み取り、暗号化用の一連の文字列として処理します。次に、Random クラスを使用して、暗号化する文字をハッシュ テーブルからランダムに選択します。メッセージを復号化するプロセスは、暗号化の逆です。StringBuilder クラスを使用して、暗号化および復号化されたメッセージを構築します。
コード部分は次のとおりです。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
public class MessageEncryptor {
public static void main(String[] args) {
Map<Character, List<Character>> hashTable;
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hashtable.ser"))) {
hashTable = (Map<Character, List<Character>>) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return;
}
System.out.print("请输入要加密的明文:");
Scanner scanner = new Scanner(System.in);
String message = scanner.nextLine();
//对明文做处理,只保留字母、数字和空格,并把字母转换为小写
message = message.replaceAll("[^a-zA-Z0-9\\s]", "").toLowerCase();
StringBuilder encryptedMessage = new StringBuilder();
for (char c : message.toCharArray()) {
encryptedMessage.append(hashTable.get(c).get(new Random().nextInt(hashTable.get(c).size()))); // choose one of the characters at random
}
System.out.println("密文: " + encryptedMessage);
StringBuilder decryptedMessage = new StringBuilder();
for (char c : encryptedMessage.toString().toCharArray()) {
if (c == hashTable.get(' ').get(0)) {
decryptedMessage.append(' ');
} else {
for (Map.Entry<Character, List<Character>> entry : hashTable.entrySet()) {
if (entry.getValue().contains(c)) {
decryptedMessage.append(entry.getKey());
break;
}
}
}
}
System.out.println("解密: " + decryptedMessage.toString());
}
}
4. アルゴリズムのパフォーマンス
4.1 セキュリティ
文字のリストをランダムに生成し、ハッシュ テーブルを使用して文字をランダムな文字にマッピングすることにより、アルゴリズムのセキュリティを保証できる可能性があります。攻撃者がハッシュ テーブル内のマッピング関係を推測することは困難であるため、暗号化されたメッセージを解読することは困難です。
4.2 実用性
私たちのアルゴリズムは非常にシンプルで、実装も使用も簡単です。ハッシュ テーブルには 37 文字が保存されるため、文字、数字、特殊文字を含むさまざまな種類のメッセージを暗号化できます。同時に、ハッシュ テーブルの値はランダムであるため、文字ごとに異なる暗号化メッセージを生成でき、セキュリティが強化されます。
4.3 パフォーマンス
アルゴリズムのパフォーマンスを評価するためにいくつかのベンチマークを実行しました。テスト環境はWindows 11、プロセッサーは第12世代 Intel® Core™ i5-12500H 2.50 GHz、メモリは16GBです。テストでは、暗号化と復号化のために長さ 100 の文字列 100,000 個がランダムに生成され、実行時間が記録されました。テスト結果は、平均暗号化時間は 0.0117 ミリ秒、平均復号時間は 2.41997 ミリ秒であることを示しています。アルゴリズムが非常にシンプルなため、実用上の応答性が良好です。
テスト クラスは BenchmarkTest クラスで、コードは次のとおりです。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class BenchmarkTest {
public static void main(String[] args) {
Map<Character, List<Character>> hashTable;
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hashtable.ser"))) {
hashTable = (Map<Character, List<Character>>) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return;
}
int numTests = 100000;
int messageLength = 100;
long encryptionTime = 0;
long decryptionTime = 0;
for (int i = 0; i < numTests; i++) {
String message = generateRandomString(messageLength);
long startTime = System.currentTimeMillis();
String encryptedMessage = encryptMessage(hashTable, message);
long endTime = System.currentTimeMillis();
encryptionTime += endTime - startTime;
startTime = System.currentTimeMillis();
String decryptedMessage = decryptMessage(hashTable, encryptedMessage);
endTime = System.currentTimeMillis();
decryptionTime += endTime - startTime;
}
double averageEncryptionTime = (double) encryptionTime / numTests;
double averageDecryptionTime = (double) decryptionTime / numTests;
System.out.println("平均加密时间: " + averageEncryptionTime + " milliseconds");
System.out.println("平均解密时间: " + averageDecryptionTime + " milliseconds");
}
private static String generateRandomString(int length) {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ";
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
int index = random.nextInt(chars.length());
sb.append(chars.charAt(index));
}
return sb.toString();
}
private static String encryptMessage(Map<Character, List<Character>> hashTable, String message) {
message = message.replaceAll("[^a-zA-Z0-9\\s]", "").toLowerCase();
StringBuilder encryptedMessage = new StringBuilder();
for (char c : message.toCharArray()) {
encryptedMessage.append(hashTable.get(c).get(new Random().nextInt(hashTable.get(c).size())));
}
return encryptedMessage.toString();
}
private static String decryptMessage(Map<Character, List<Character>> hashTable, String encryptedMessage) {
StringBuilder decryptedMessage = new StringBuilder();
for (char c : encryptedMessage.toCharArray()) {
if (c == hashTable.get(' ').get(0)) {
decryptedMessage.append(' ');
} else {
for (Map.Entry<Character, List<Character>> entry : hashTable.entrySet()) {
if (entry.getValue().contains(c)) {
decryptedMessage.append(entry.getKey());
break;
}
}
}
}
return decryptedMessage.toString();
}
}
テスト結果を図に示します。
5. アルゴリズム表示
以下に示すように:
6. 結論
この記事では、ハッシュ テーブルに基づく単純な暗号化アルゴリズムを紹介します。パフォーマンスに関しては、ベンチマークを実行し、良好な結果が得られました。ただし、私のアルゴリズムは対称暗号化アルゴリズムであるため、鍵の配布と管理にいくつかの困難がある可能性があります。また、このアルゴリズムが安全性と実用性が高いかどうか、あるいは多くの種類のメッセージ暗号化に適しているかどうかはわかりませんが、もしよろしければ、テストしていただくこともできますので、よろしくお願いします。