diff --git a/device-fingerprint-tool/src/main/java/com/sunyard/cisd/Main.java b/device-fingerprint-tool/src/main/java/com/sunyard/cisd/Main.java index 0269019..241dfde 100644 --- a/device-fingerprint-tool/src/main/java/com/sunyard/cisd/Main.java +++ b/device-fingerprint-tool/src/main/java/com/sunyard/cisd/Main.java @@ -3,6 +3,7 @@ package com.sunyard.cisd; import java.nio.charset.StandardCharsets; import java.security.PublicKey; import java.util.Base64; +import java.util.Map; public class Main { @@ -11,54 +12,87 @@ public class Main { private static final String SIGN_SM3_FILE = DEVICE_DIR + "/dev.sign.sm3"; private static final String PUBLIC_KEY_FILE = DEVICE_DIR + "/dev.fingerprint.pub"; private static final String PUBLIC_KEY_SM3_FILE = DEVICE_DIR + "/dev.fingerprint.pub.sm3"; + private static final String FINGERPRINT_DATA_FILE = DEVICE_DIR + "/dev.fingerprint.data"; private static final String PRIVATE_KEY_PATH = "/sm2_private_key.pem"; + private static final String PUBLIC_KEY_PATH = "/sm2_public_key.pem"; public static void main(String[] args) { + if (args.length == 0) { + printHelp(); + return; + } + + String command = args[0]; + try { - DeviceFingerprintService service = new DeviceFingerprintService(); - DeviceFingerprint fingerprint = service.getDeviceFingerprint(); - - System.out.println("=== 设备指纹信息 ==="); - System.out.println("主板序列号: " + fingerprint.getMotherboardSerialNumber()); - System.out.println("设备序列号: " + fingerprint.getDeviceSerialNumber()); - System.out.println("CPU型号: " + fingerprint.getCpuModel()); - System.out.println("CPU序列号: " + fingerprint.getCpuSerialNumber()); - System.out.println("内存大小: " + fingerprint.getMemorySize()); - System.out.println("首块网卡MAC地址: " + fingerprint.getFirstNetworkMacAddress()); - System.out.println("硬盘序列号: " + fingerprint.getHardDiskSerialNumber()); - - String plainText = buildPlainText(fingerprint); - System.out.println("\n拼接后的原文: " + plainText); - - byte[] signature = SM2Util.sign(plainText.getBytes(StandardCharsets.UTF_8), PRIVATE_KEY_PATH); - System.out.println("签名结果(Base64): " + Base64.getEncoder().encodeToString(signature)); - - PublicKey publicKey = SM2Util.loadPublicKey("/sm2_public_key.pem"); - String publicKeyPEM = SM2Util.publicKeyToPEM(publicKey); - - SM3Util.writeFile(SIGN_FILE, signature); - System.out.println("签名文件已保存: " + SIGN_FILE); - - String signSm3 = SM3Util.sm3DigestHex(signature); - SM3Util.writeFile(SIGN_SM3_FILE, signSm3); - System.out.println("签名SM3校验值已保存: " + SIGN_SM3_FILE + " (" + signSm3 + ")"); - - SM3Util.writeFile(PUBLIC_KEY_FILE, publicKeyPEM); - System.out.println("公钥文件已保存: " + PUBLIC_KEY_FILE); - - String publicKeySm3 = SM3Util.sm3DigestHex(publicKeyPEM.getBytes(StandardCharsets.UTF_8)); - SM3Util.writeFile(PUBLIC_KEY_SM3_FILE, publicKeySm3); - System.out.println("公钥SM3校验值已保存: " + PUBLIC_KEY_SM3_FILE + " (" + publicKeySm3 + ")"); - - boolean verified = SM2Util.verify(plainText.getBytes(StandardCharsets.UTF_8), signature, publicKey); - System.out.println("\n签名验证结果: " + verified); - + switch (command) { + case "help": + printHelp(); + break; + case "info": + showDeviceInfo(); + break; + case "fingerprint-gen": + generateFingerprint(); + break; + + case "fingerprint-vertify": + verifyFingerprint(); + break; + case "mac-gen": + if (args.length < 3) { + System.err.println("错误: mac-gen 需要两个参数 - 文件夹路径 和 输出文件路径"); + System.out.println("用法: mac-gen <文件夹路径> <输出文件路径>"); + } else { + generateMAC(args[1], args[2]); + } + break; + case "mac-vertify": + if (args.length < 3) { + System.err.println("错误: mac-verify 需要两个参数 - 文件夹路径 和 SM3文件路径"); + System.out.println("用法: mac-verify <文件夹路径> "); + } else { + verifyMAC(args[1], args[2]); + } + break; + default: + System.err.println("未知命令: " + command); + printHelp(); + break; + } } catch (Exception e) { System.err.println("处理过程中发生错误: " + e.getMessage()); e.printStackTrace(); } } + private static void printHelp() { + System.out.println("设备指纹工具 - 使用说明"); + System.out.println(); + System.out.println("可用命令:"); + System.out.println(" help - 显示帮助信息"); + System.out.println(" info - 获取并显示设备信息"); + System.out.println(" fingerprint-gen - 获取设备信息并生成设备指纹输出到文件"); + System.out.println(" fingerprint-vertify - 获取设备信息并验证设备指纹"); + System.out.println(" mac-gen <文件夹> <输出文件> - 对指定文件夹下所有文件计算SM3并输出到文件"); + System.out.println(" mac-vertify <文件夹> - 验证指定文件夹下所有文件的SM3值"); + System.out.println(); + } + + private static void showDeviceInfo() throws Exception { + DeviceFingerprintService service = new DeviceFingerprintService(); + DeviceFingerprint fingerprint = service.getDeviceFingerprint(); + + System.out.println("=== 设备信息 ==="); + System.out.println("主板序列号: " + fingerprint.getMotherboardSerialNumber()); + System.out.println("设备序列号: " + fingerprint.getDeviceSerialNumber()); + System.out.println("CPU型号: " + fingerprint.getCpuModel()); + System.out.println("CPU序列号: " + fingerprint.getCpuSerialNumber()); + System.out.println("内存大小: " + fingerprint.getMemorySize()); + System.out.println("首块网卡MAC地址: " + fingerprint.getFirstNetworkMacAddress()); + System.out.println("硬盘序列号: " + fingerprint.getHardDiskSerialNumber()); + } + private static String buildPlainText(DeviceFingerprint fingerprint) { return fingerprint.getMotherboardSerialNumber() + fingerprint.getDeviceSerialNumber() + @@ -68,4 +102,103 @@ public class Main { fingerprint.getFirstNetworkMacAddress() + fingerprint.getHardDiskSerialNumber(); } + + private static void generateFingerprint() throws Exception { + DeviceFingerprintService service = new DeviceFingerprintService(); + DeviceFingerprint fingerprint = service.getDeviceFingerprint(); + + System.out.println("=== 设备指纹信息 ==="); + System.out.println("主板序列号: " + fingerprint.getMotherboardSerialNumber()); + System.out.println("设备序列号: " + fingerprint.getDeviceSerialNumber()); + System.out.println("CPU型号: " + fingerprint.getCpuModel()); + System.out.println("CPU序列号: " + fingerprint.getCpuSerialNumber()); + System.out.println("内存大小: " + fingerprint.getMemorySize()); + System.out.println("首块网卡MAC地址: " + fingerprint.getFirstNetworkMacAddress()); + System.out.println("硬盘序列号: " + fingerprint.getHardDiskSerialNumber()); + + String plainText = buildPlainText(fingerprint); + System.out.println("\n拼接后的原文: " + plainText); + + byte[] signature = SM2Util.sign(plainText.getBytes(StandardCharsets.UTF_8), PRIVATE_KEY_PATH); + System.out.println("签名结果(Base64): " + Base64.getEncoder().encodeToString(signature)); + + PublicKey publicKey = SM2Util.loadPublicKey(PUBLIC_KEY_PATH); + String publicKeyPEM = SM2Util.publicKeyToPEM(publicKey); + + SM3Util.writeFile(SIGN_FILE, signature); + System.out.println("签名文件已保存: " + SIGN_FILE); + + String signSm3 = SM3Util.sm3DigestHex(signature); + SM3Util.writeFile(SIGN_SM3_FILE, signSm3); + System.out.println("签名SM3校验值已保存: " + SIGN_SM3_FILE + " (" + signSm3 + ")"); + + SM3Util.writeFile(PUBLIC_KEY_FILE, publicKeyPEM); + System.out.println("公钥文件已保存: " + PUBLIC_KEY_FILE); + + String publicKeySm3 = SM3Util.sm3DigestHex(publicKeyPEM.getBytes(StandardCharsets.UTF_8)); + SM3Util.writeFile(PUBLIC_KEY_SM3_FILE, publicKeySm3); + System.out.println("公钥SM3校验值已保存: " + PUBLIC_KEY_SM3_FILE + " (" + publicKeySm3 + ")"); + + SM3Util.writeFile(FINGERPRINT_DATA_FILE, plainText); + System.out.println("设备指纹数据已保存: " + FINGERPRINT_DATA_FILE); + + boolean verified = SM2Util.verify(plainText.getBytes(StandardCharsets.UTF_8), signature, publicKey); + System.out.println("\n签名验证结果: " + verified); + } + + private static void verifyFingerprint() throws Exception { + DeviceFingerprintService service = new DeviceFingerprintService(); + DeviceFingerprint fingerprint = service.getDeviceFingerprint(); + + System.out.println("=== 当前设备信息 ==="); + System.out.println("主板序列号: " + fingerprint.getMotherboardSerialNumber()); + System.out.println("设备序列号: " + fingerprint.getDeviceSerialNumber()); + System.out.println("CPU型号: " + fingerprint.getCpuModel()); + System.out.println("CPU序列号: " + fingerprint.getCpuSerialNumber()); + System.out.println("内存大小: " + fingerprint.getMemorySize()); + System.out.println("首块网卡MAC地址: " + fingerprint.getFirstNetworkMacAddress()); + System.out.println("硬盘序列号: " + fingerprint.getHardDiskSerialNumber()); + + String plainText = buildPlainText(fingerprint); + System.out.println("\n当前拼接原文: " + plainText); + + String savedPlainText = SM3Util.readFile(FINGERPRINT_DATA_FILE).trim(); + System.out.println("保存的拼接原文: " + savedPlainText); + + byte[] signature = SM3Util.readFileBytes(SIGN_FILE); + PublicKey publicKey = SM2Util.loadPublicKey(PUBLIC_KEY_PATH); + + boolean dataMatch = plainText.equals(savedPlainText); + boolean signatureVerified = SM2Util.verify(savedPlainText.getBytes(StandardCharsets.UTF_8), signature, publicKey); + + System.out.println("\n=== 验证结果 ==="); + System.out.println("设备信息匹配: " + dataMatch); + System.out.println("签名验证: " + signatureVerified); + System.out.println("总体验证: " + (dataMatch && signatureVerified)); + } + + private static void generateMAC(String directoryPath, String outputFilePath) throws Exception { + System.out.println("正在计算文件夹 SM3: " + directoryPath); + Map sm3Map = SM3Util.calculateDirectorySM3(directoryPath); + + System.out.println("\n发现 " + sm3Map.size() + " 个文件:"); + for (Map.Entry entry : sm3Map.entrySet()) { + System.out.println(" " + entry.getKey() + " : " + entry.getValue()); + } + + SM3Util.writeSM3File(sm3Map, outputFilePath); + System.out.println("\nSM3 文件已保存: " + outputFilePath); + } + + private static void verifyMAC(String directoryPath, String sm3FilePath) throws Exception { + System.out.println("正在验证文件夹 SM3: " + directoryPath); + System.out.println("使用 SM3 文件: " + sm3FilePath); + System.out.println(); + + boolean verified = SM3Util.verifyDirectorySM3(directoryPath, sm3FilePath); + + System.out.println(); + System.out.println("=== 验证结果 ==="); + System.out.println("完整性验证: " + verified); + } } diff --git a/device-fingerprint-tool/src/main/java/com/sunyard/cisd/SM3Util.java b/device-fingerprint-tool/src/main/java/com/sunyard/cisd/SM3Util.java index f34a283..6628d22 100644 --- a/device-fingerprint-tool/src/main/java/com/sunyard/cisd/SM3Util.java +++ b/device-fingerprint-tool/src/main/java/com/sunyard/cisd/SM3Util.java @@ -3,10 +3,15 @@ package com.sunyard.cisd; import org.bouncycastle.crypto.digests.SM3Digest; import org.bouncycastle.util.encoders.Hex; +import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; public class SM3Util { @@ -23,6 +28,103 @@ public class SM3Util { return Hex.toHexString(digest); } + public static String sm3FileHex(String filePath) throws Exception { + File file = new File(filePath); + if (!file.exists() || !file.isFile()) { + throw new IllegalArgumentException("File not found: " + filePath); + } + + try (FileInputStream fis = new FileInputStream(file)) { + SM3Digest digest = new SM3Digest(); + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = fis.read(buffer)) != -1) { + digest.update(buffer, 0, bytesRead); + } + byte[] result = new byte[digest.getDigestSize()]; + digest.doFinal(result, 0); + return Hex.toHexString(result); + } + } + + public static Map calculateDirectorySM3(String directoryPath) throws Exception { + File dir = new File(directoryPath); + if (!dir.exists() || !dir.isDirectory()) { + throw new IllegalArgumentException("Directory not found: " + directoryPath); + } + + Map sm3Map = new HashMap<>(); + calculateDirectorySM3Recursive(dir, dir.getAbsolutePath(), sm3Map); + return sm3Map; + } + + private static void calculateDirectorySM3Recursive(File dir, String basePath, Map sm3Map) throws Exception { + File[] files = dir.listFiles(); + if (files == null) return; + + for (File file : files) { + if (file.isDirectory()) { + calculateDirectorySM3Recursive(file, basePath, sm3Map); + } else { + String relativePath = file.getAbsolutePath().substring(basePath.length() + 1); + String sm3Value = sm3FileHex(file.getAbsolutePath()); + sm3Map.put(relativePath, sm3Value); + } + } + } + + public static void writeSM3File(Map sm3Map, String outputFilePath) throws Exception { + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : sm3Map.entrySet()) { + sb.append(entry.getKey()).append("|").append(entry.getValue()).append("\n"); + } + writeFile(outputFilePath, sb.toString()); + } + + public static Map readSM3File(String filePath) throws Exception { + Map sm3Map = new HashMap<>(); + try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + String line; + while ((line = reader.readLine()) != null) { + String[] parts = line.split("\\|", 2); + if (parts.length == 2) { + sm3Map.put(parts[0], parts[1]); + } + } + } + return sm3Map; + } + + public static boolean verifyDirectorySM3(String directoryPath, String sm3FilePath) throws Exception { + Map savedSM3 = readSM3File(sm3FilePath); + Map currentSM3 = calculateDirectorySM3(directoryPath); + + boolean allMatch = true; + + for (Map.Entry entry : savedSM3.entrySet()) { + String filePath = entry.getKey(); + String savedHash = entry.getValue(); + String currentHash = currentSM3.get(filePath); + + if (currentHash == null) { + System.out.println("文件缺失: " + filePath); + allMatch = false; + } else if (!savedHash.equals(currentHash)) { + System.out.println("文件校验失败: " + filePath + " (期望: " + savedHash + ", 实际: " + currentHash + ")"); + allMatch = false; + } + } + + for (String filePath : currentSM3.keySet()) { + if (!savedSM3.containsKey(filePath)) { + System.out.println("新增文件: " + filePath); + allMatch = false; + } + } + + return allMatch; + } + public static void writeFile(String filePath, byte[] content) throws Exception { File file = new File(filePath); File parentDir = file.getParentFile(); @@ -37,4 +139,24 @@ public class SM3Util { public static void writeFile(String filePath, String content) throws Exception { writeFile(filePath, content.getBytes(StandardCharsets.UTF_8)); } + + public static String readFile(String filePath) throws Exception { + StringBuilder sb = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + String line; + while ((line = reader.readLine()) != null) { + sb.append(line).append("\n"); + } + } + return sb.toString(); + } + + public static byte[] readFileBytes(String filePath) throws Exception { + File file = new File(filePath); + try (FileInputStream fis = new FileInputStream(file)) { + byte[] content = new byte[(int) file.length()]; + fis.read(content); + return content; + } + } }