【Java】基于哈希表的随机字符替换加密算法
一、简介
1.1 背景
在现代社会,信息的传输和保密显得尤为重要。为了确保数据安全,人们经常使用各种加密算法来加密信息。然而,常规的加密算法被攻击者破解的风险也越来越大。因此,开发一种更加安全的加密算法显得非常重要。
1.2 目的
本文的目的是介绍一种基于哈希表的简单加密算法,但是我认为该算法应该具有较高的安全性和实用性。文章将从算法的设计和实现等方面进行详细讨论。
二、算法设计
2.1 HashTableCreator类
在该算法中,我们首先需要创建一个哈希表来保存映射关系。HashTableCreator类用于创建哈希表。我们可以在哈希表中存储26个字母、10个数字和一个空格,总共37个字符。对于每个字符,我们随机生成一组由1771个不同的字符组成的列表,并将该列表与字符映射到哈希表中。
2.2 MessageEncryptor类
MessageEncryptor类用于加密和解密消息。该类从哈希表中获取与每个输入字符对应的随机字符,并将其组合成加密后的字符串。要解密消息,我们需要将加密后的字符与哈希表中的值进行比较,并确定它所代表的字符。
三、算法实现
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.1 安全性
通过随机生成字符列表和使用哈希表来映射字符和随机字符,或许可以保证算法的安全性。攻击者难以猜测哈希表中的映射关系,因此难以破解加密消息。
4.2 实用性
我们的算法非常简单,容易实现和使用。由于哈希表中存储了37个字符,因此可以加密多种类型的消息,包括字母、数字和特殊字符等。同时,哈希表中的值是随机的,因此可以为每个字符生成不同的加密消息,增强了安全性。
4.3 性能
我进行了一些基准测试,以评估算法的性能。测试环境为Windows 11,处理器为12th Gen Intel® Core™ i5-12500H 2.50 GHz,内存为16GB。测试中,随机生成100000个长度为100的字符串进行加密和解密,并记录了执行时间。测试结果表明,平均加密时间为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();
}
}
测试结果如图所示:
五、算法展示
如下图所示:
六、结论
本文介绍了一种基于哈希表的简单加密算法。在性能方面,我进行了基准测试并得出了良好的结果。然而,由于我的算法是一种对称加密算法,因此在密钥分发和管理方面可能会存在一些困难。并且我不知道该算法是否具有较高的安全性和实用性或是是否适用于多种类型的消息加密,如果有人愿意的话也可以帮我测试一下,非常感谢。