java实现消息认证码签名与验证:想改进一下实验代码,要签名的对象为参数dataSetFolder路径中的每个文件的内容(每个文件都为英文电子邮件)、参数positionMap和一个随循环次数自增的参数fileCounter。每次循环都生成一个MAC签名,并验证签名内容的正确性,如正确则系统输出Accept,并把MAC签名写成一个txt格式的文件保存在本地且txt文件命名为自增的数字序号。
部分代码如图:
程序代码如下:
import client.utils.*;
import it.unisa.dia.gas.jpbc.Element;
import orestes.bloomfilter.CountingBloomFilter;
import orestes.bloomfilter.FilterBuilder;
import pojo.PrivateKey;
import pojo.PublicKey;
import server.Search;
import server.utils.HomoEncryption_Server;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Phrase_multi {
public static void main(String[] args) {
KeyGenUtils.genKey();
Object[] key = KeyGenUtils.getKeyFromFile("key.data");
PublicKey publicKey = (PublicKey) key[0];
PrivateKey privateKey = (PrivateKey) key[1];
CountingBloomFilter<Object> cbf = new FilterBuilder(1000000, 0.01)
.buildCountingBloomFilter();
ConcurrentHashMap<Integer, HashMap<String, ArrayList<Element>>> filesMaps = new ConcurrentHashMap<>();
File dataSetFolder = new File("C:\\mypaperdataset\\enron\\version2\\10000");
ExecutorService executorService = Executors.newCachedThreadPool();
long s = System.currentTimeMillis();
AtomicInteger fileCounter = new AtomicInteger(1);
for (File file : dataSetFolder.listFiles()) {
// if (count==7000) break;
// count++;
Integer node = NodeGen_Client.getNode();
executorService.execute(()->{
System.out.println("正在处理文件:" + file.getName() +"分配的节点:"+node);
List<String> extracted = ExtractKeyword.extract_easy(file);//一个文件提取关键词耗费5ms
IndexBuilding.buildCBF_Batch(extracted, node, cbf);
HashMap<String, ArrayList<Element>> positionMap = IndexBuilding.buildHashTable_exp(extracted, privateKey);
filesMaps.put(node, positionMap);
});
}
executorService.shutdown();
try {
while (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
System.out.println("线程池没有关闭");
// System.out.println("isTerminated:" + executorService.isTerminated());
ThreadPoolExecutor executor = (ThreadPoolExecutor) executorService;
System.out.println("剩余线程数: "+executor.getActiveCount());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
long e = System.currentTimeMillis();
System.out.println("线程池已经关闭");
System.out.println("isTerminated:" + executorService.isTerminated());
System.out.println("用时:"+(e-s)+"毫秒");
// 搜索
HomoEncryption_Client homo_client = new HomoEncryption_Client(privateKey, publicKey);
Element elementX = homo_client.getElementX();
Element elementY = homo_client.getElementY();
while (true) {
ArrayList<String> keywords = new ArrayList<>();
while (true) {
System.out.println("请输入:");
Scanner input = new Scanner(System.in);
String next = input.next();
if (next.equals("0")) {
System.out.println("开始查询");
break;
}
keywords.add(MyHashUtils.md5(next));
}
HomoEncryption_Server homo_server = new HomoEncryption_Server(publicKey);
long kk = System.nanoTime();
List<Integer> search_result1 = Search.searchKeywords(keywords, cbf);
long ll = System.nanoTime();
System.out.println("普通查询完成,用时:"+(ll-kk)+"ns 查询到了"+search_result1.size()+"个文件");
long pp = System.nanoTime();
List<Integer> search_result2 = Search.searchKeywords_Phrase(keywords, cbf, filesMaps, homo_server, elementX, elementY);
long jj = System.nanoTime();
System.out.println("词组查询完成,用时:"+(jj-pp)+"ms 查询到了"+search_result2.size()+"个文件");
}
}
}
以下是修改后的代码,根据你的要求添加了MAC签名的功能:
import client.utils.*;
import it.unisa.dia.gas.jpbc.Element;
import orestes.bloomfilter.CountingBloomFilter;
import orestes.bloomfilter.FilterBuilder;
import pojo.PrivateKey;
import pojo.PublicKey;
import server.Search;
import server.utils.HomoEncryption_Server;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Phrase_multi {
private static final String MAC_ALGORITHM = "HmacSHA256";
public static void main(String[] args) {
KeyGenUtils.genKey();
Object[] key = KeyGenUtils.getKeyFromFile("key.data");
PublicKey publicKey = (PublicKey) key[0];
PrivateKey privateKey = (PrivateKey) key[1];
CountingBloomFilter<Object> cbf = new FilterBuilder(1000000, 0.01)
.buildCountingBloomFilter();
ConcurrentHashMap<Integer, HashMap<String, ArrayList<Element>>> filesMaps = new ConcurrentHashMap<>();
File dataSetFolder = new File("C:\\mypaperdataset\\enron\\version2\\10000");
ExecutorService executorService = Executors.newCachedThreadPool();
long s = System.currentTimeMillis();
AtomicInteger fileCounter = new AtomicInteger(1);
for (File file : dataSetFolder.listFiles()) {
Integer node = NodeGen_Client.getNode();
executorService.execute(() -> {
System.out.println("正在处理文件:" + file.getName() + " 分配的节点:" + node);
List<String> extracted = ExtractKeyword.extract_easy(file);
IndexBuilding.buildCBF_Batch(extracted, node, cbf);
HashMap<String, ArrayList<Element>> positionMap = IndexBuilding.buildHashTable_exp(extracted, privateKey);
filesMaps.put(node, positionMap);
// Generate and verify MAC signature
String macSignature = generateMacSignature(file.getAbsolutePath(), positionMap, fileCounter.getAndIncrement());
if (verifyMacSignature(file.getAbsolutePath(), macSignature, positionMap, fileCounter.get() - 1)) {
System.out.println("Accept");
saveMacSignatureToFile(fileCounter.get() - 1, macSignature);
}
});
}
executorService.shutdown();
try {
while (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
System.out.println("线程池没有关闭");
ThreadPoolExecutor executor = (ThreadPoolExecutor) executorService;
System.out.println("剩余线程数: " + executor.getActiveCount());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
long e = System.currentTimeMillis();
System.out.println("线程池已经关闭");
System.out.println("isTerminated: " + executorService.isTerminated());
System.out.println("用时: " + (e - s) + "毫秒");
// 搜索
HomoEncryption_Client homo_client = new HomoEncryption_Client(privateKey, publicKey);
Element elementX = homo_client.getElementX();
Element elementY = homo_client.getElementY();
while (true) {
ArrayList<String> keywords = new ArrayList<>();
while (true) {
System.out.println("请输入:");
Scanner input = new Scanner(System.in);
String next = input.next();
if (next.equals("0")) {
System.out.println("开始查询");
break;
}
keywords.add(MyHashUtils.md5(next));
}
HomoEncryption_Server homo_server = new HomoEncryption_Server(publicKey);
long kk = System.nanoTime();
List<Integer> search_result1 = Search.searchKeywords(keywords, cbf);
long ll = System.nanoTime();
System.out.println("普通查询完成,用时:" + (ll - kk) + "ns 查询到了" + search_result1.size() + "个文件");
long pp = System.nanoTime();
List<Integer> search_result2 = Search.searchKeywords_Phrase(keywords, cbf, filesMaps, homo_server, elementX, elementY);
long jj = System.nanoTime();
System.out.println("词组查询完成,用时:" + (jj - pp) + "ms 查询到了" + search_result2.size() + "个文件");
}
}
private static String generateMacSignature(String filePath, HashMap<String, ArrayList<Element>> positionMap, int fileCounter) {
try {
String data = readFileAsString(filePath);
StringBuilder sb = new StringBuilder();
sb.append(data);
for (String keyword : positionMap.keySet()) {
sb.append(keyword);
for (Element element : positionMap.get(keyword)) {
sb.append(element);
}
}
String dataToSign = sb.toString();
Mac mac = Mac.getInstance(MAC_ALGORITHM);
SecretKey secretKey = generateMacSecretKey(fileCounter);
mac.init(secretKey);
byte[] signatureBytes = mac.doFinal(dataToSign.getBytes());
return bytesToHexString(signatureBytes);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static boolean verifyMacSignature(String filePath, String macSignature, HashMap<String, ArrayList<Element>> positionMap, int fileCounter) {
try {
String data = readFileAsString(filePath);
StringBuilder sb = new StringBuilder();
sb.append(data);
for (String keyword : positionMap.keySet()) {
sb.append(keyword);
for (Element element : positionMap.get(keyword)) {
sb.append(element);
}
}
String dataToVerify = sb.toString();
Mac mac = Mac.getInstance(MAC_ALGORITHM);
SecretKey secretKey = generateMacSecretKey(fileCounter);
mac.init(secretKey);
byte[] signatureBytes = mac.doFinal(dataToVerify.getBytes());
String generatedSignature = bytesToHexString(signatureBytes);
return macSignature.equals(generatedSignature);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private static SecretKey generateMacSecretKey(int fileCounter) {
try {
KeyGenerator keyGen = KeyGenerator.getInstance(MAC_ALGORITHM);
keyGen.init(256); // Adjust key size as needed
SecretKey secretKey = keyGen.generateKey();
byte[] encodedKey = secretKey.getEncoded();
Path keyFilePath = Path.of("mac_keys", fileCounter + ".txt");
Files.createDirectories(keyFilePath.getParent());
Files.write(keyFilePath, encodedKey, StandardOpenOption.CREATE);
return secretKey;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String readFileAsString(String filePath) {
try {
return new String(Files.readAllBytes(Path.of(filePath)));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static void saveMacSignatureToFile(int fileCounter, String macSignature) {
try {
String fileName = fileCounter + ".txt";
FileWriter writer = new FileWriter(fileName);
writer.write(macSignature);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
这个修改后的代码添加了以下功能:
在循环处理每个文件时生成MAC签名,并验证签名的正确性。
如果签名验证通过,将MAC签名保存到本地以自增的数字序号作为文件名的txt文件中。
请确保在运行代码之前创建名为mac_keys的文件夹,用于保存生成的MAC密钥。
注意:该代码只提供了基本的MAC签名功能,但并未包含数据完整性和安全性的全面保护。
你是想改什么?
问题回答:
实现消息认证码的签名和验证可以使用Java提供的加密技术,具体来说,可以使用Java加密标准(JCE)提供的加密库,如增强型加密标准(AES)、数据加密标准(DES)等等。
下面是实现消息认证码的签名和验证的大体思路:
下面是一个简单的示例代码,用于对消息进行签名和验证:
import java.security.*;
public class MessageAuthenticationCode {
private static final String HMAC_SHA512 = "HmacSHA512";
public static byte[] createHmac(byte[] key, byte[] data) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, HMAC_SHA512);
Mac mac = Mac.getInstance(HMAC_SHA512);
mac.init(secretKeySpec);
return mac.doFinal(data);
}
public static void main(String[] args) throws Exception {
String message = "this is a sample message";
byte[] key = "12345678".getBytes();
byte[] hmac = createHmac(key, message.getBytes());
System.out.println("Message: " + message);
System.out.println("HMAC: " + new String(hmac));
boolean isValid = checkHmac(key, message.getBytes(), hmac);
System.out.println("Is valid? " + isValid);
}
public static boolean checkHmac(byte[] key, byte[] data, byte[] hmac) throws Exception {
byte[] newData = createHmac(key, data);
if (newData.length != hmac.length) {
return false;
}
for (int i = 0; i < newData.length; i++) {
if (newData[i] != hmac[i]) {
return false;
}
}
return true;
}
}
在上面的示例代码中,我们使用了Java提供的javax.crypto.Mac类对消息进行签名。对于消息,我们使用了字符串,对于密钥,我们使用了字节数组。如果需要生成更强的密钥,可以使用Java Cryptography Extension(JCE)提供的KeyGenerator类。
以上是生成签名的代码,如果需要验证签名,则需要将签名和产生签名的消息都传递到接收方,接收方使用相同的方式生成签名,并将两个签名进行比较。如果两个签名相同,则认为消息是真实的。
总结:Java提供了许多用于加密和签名的库,可以使用这些库轻松地实现消息认证码的签名和验证。