编写设备指纹获取逻辑

This commit is contained in:
cheney 2026-05-13 15:01:28 +08:00
parent 7ea0325283
commit 3779a055e0
7 changed files with 344 additions and 2 deletions

View File

@ -57,8 +57,6 @@
内存大小
首块网卡MAC地址
硬盘序列号
起始日期
终止日期
}
设备指纹是设备指纹信息的 SM2 签名pkcs1 格式)。

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sunyard.cisd</groupId>
<artifactId>device-fingerprint-tool</artifactId>
<version>1.0.0</version>
<name>device-fingerprint-tool</name>
<description>设备指纹信息获取工具</description>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.sunyard.cisd.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,83 @@
package com.sunyard.cisd;
public class DeviceFingerprint {
private String motherboardSerialNumber;
private String deviceSerialNumber;
private String cpuModel;
private String cpuSerialNumber;
private String memorySize;
private String firstNetworkMacAddress;
private String hardDiskSerialNumber;
public DeviceFingerprint() {
}
public String getMotherboardSerialNumber() {
return motherboardSerialNumber;
}
public void setMotherboardSerialNumber(String motherboardSerialNumber) {
this.motherboardSerialNumber = motherboardSerialNumber;
}
public String getDeviceSerialNumber() {
return deviceSerialNumber;
}
public void setDeviceSerialNumber(String deviceSerialNumber) {
this.deviceSerialNumber = deviceSerialNumber;
}
public String getCpuModel() {
return cpuModel;
}
public void setCpuModel(String cpuModel) {
this.cpuModel = cpuModel;
}
public String getCpuSerialNumber() {
return cpuSerialNumber;
}
public void setCpuSerialNumber(String cpuSerialNumber) {
this.cpuSerialNumber = cpuSerialNumber;
}
public String getMemorySize() {
return memorySize;
}
public void setMemorySize(String memorySize) {
this.memorySize = memorySize;
}
public String getFirstNetworkMacAddress() {
return firstNetworkMacAddress;
}
public void setFirstNetworkMacAddress(String firstNetworkMacAddress) {
this.firstNetworkMacAddress = firstNetworkMacAddress;
}
public String getHardDiskSerialNumber() {
return hardDiskSerialNumber;
}
public void setHardDiskSerialNumber(String hardDiskSerialNumber) {
this.hardDiskSerialNumber = hardDiskSerialNumber;
}
@Override
public String toString() {
return "DeviceFingerprint{" +
"motherboardSerialNumber='" + motherboardSerialNumber + '\'' +
", deviceSerialNumber='" + deviceSerialNumber + '\'' +
", cpuModel='" + cpuModel + '\'' +
", cpuSerialNumber='" + cpuSerialNumber + '\'' +
", memorySize='" + memorySize + '\'' +
", firstNetworkMacAddress='" + firstNetworkMacAddress + '\'' +
", hardDiskSerialNumber='" + hardDiskSerialNumber + '\'' +
'}';
}
}

View File

@ -0,0 +1,135 @@
package com.sunyard.cisd;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class DeviceFingerprintService {
public DeviceFingerprint getDeviceFingerprint() {
DeviceFingerprint fingerprint = new DeviceFingerprint();
String cpuSerialNumber = getCpuSerialNumber();
fingerprint.setCpuSerialNumber(cpuSerialNumber);
fingerprint.setMotherboardSerialNumber(cpuSerialNumber);
fingerprint.setCpuModel(getCpuModel());
fingerprint.setMemorySize(getMemorySize());
fingerprint.setFirstNetworkMacAddress(getFirstNetworkMacAddress());
fingerprint.setHardDiskSerialNumber(getHardDiskSerialNumber());
fingerprint.setDeviceSerialNumber(getDeviceSerialNumber());
return fingerprint;
}
private String getCpuModel() {
return executeCommand("dmidecode -t processor | grep \"Version\" | awk -F\\ '{print $2$3$4}'");
}
private String getCpuSerialNumber() {
return executeCommand("dmidecode -t processor | grep \"Serial Number\" | awk -F\\ '{print $3}'");
}
private String getHardDiskSerialNumber() {
return executeCommand("lsblk -o SERIAL /dev/sda | awk 'NR==2{print $1}'");
}
private String getMemorySize() {
String result = executeCommand("free -h | grep Mem | awk '{print $2}'");
return result != null && !result.isEmpty() ? result : "Unknown";
}
private String getFirstNetworkMacAddress() {
String result = executeCommand("ip link show | awk '/ether/ {print $2; exit}'");
return result != null && !result.isEmpty() ? result : "Unknown";
}
private String getDeviceSerialNumber() {
if (!SDFNative.isLibraryLoaded()) {
return "Unknown";
}
int hDevice = -1;
int hSession = -1;
try {
byte[] deviceName = new byte[256];
int[] deviceNameLen = new int[]{256};
int ret = SDFNative.SDF_OpenDevice(0, deviceName, deviceNameLen);
if (ret != 0) {
System.err.println("SDF_OpenDevice failed with error: " + ret);
return "Unknown";
}
hDevice = ret;
byte[] appID = "DeviceFingerprint".getBytes();
int[] sessionHandle = new int[1];
ret = SDFNative.SDF_OpenSession(hDevice, 0, appID, appID.length, sessionHandle);
if (ret != 0) {
System.err.println("SDF_OpenSession failed with error: " + ret);
return "Unknown";
}
hSession = sessionHandle[0];
SdfDeviceInfo info = new SdfDeviceInfo();
ret = SDFNative.SDF_GetDeviceInfo(hSession, info);
if (ret != 0) {
System.err.println("SDF_GetDeviceInfo failed with error: " + ret);
return "Unknown";
}
info.read();
String deviceSerial = info.getDeviceSerial();
return deviceSerial.isEmpty() ? "Unknown" : deviceSerial;
} catch (UnsatisfiedLinkError | Exception e) {
System.err.println("Failed to get device serial number from SDF: " + e.getMessage());
return "Unknown";
} finally {
if (hSession != -1) {
try {
SDFNative.SDF_CloseSession(hSession);
} catch (Exception e) {
System.err.println("Error closing session: " + e.getMessage());
}
}
if (hDevice != -1) {
try {
SDFNative.SDF_CloseDevice(hDevice);
} catch (Exception e) {
System.err.println("Error closing device: " + e.getMessage());
}
}
}
}
private String executeCommand(String command) {
try {
Process process = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", command});
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
StringBuilder output = new StringBuilder();
while ((line = reader.readLine()) != null) {
output.append(line);
}
String errorOutput = "";
while ((line = errorReader.readLine()) != null) {
errorOutput += line;
}
int exitCode = process.waitFor();
if (exitCode == 0) {
String result = output.toString().trim();
return result.isEmpty() ? "Unknown" : result;
} else {
System.err.println("Command '" + command + "' failed with exit code " + exitCode + ": " + errorOutput);
return "Unknown";
}
} catch (Exception e) {
System.err.println("Error executing command '" + command + "': " + e.getMessage());
return "Unknown";
}
}
}

View File

@ -2,5 +2,16 @@ package com.sunyard.cisd;
public class Main {
public static void main(String[] args) {
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());
}
}

View File

@ -0,0 +1,25 @@
package com.sunyard.cisd;
public class SDFNative {
private static final String SDF_LIBRARY_PATH = "/home/tms/libs/libsdf_syd1408-x64.so.1.0.0";
private static boolean libraryLoaded = false;
static {
try {
System.load(SDF_LIBRARY_PATH);
libraryLoaded = true;
} catch (UnsatisfiedLinkError e) {
System.err.println("Warning: SDF library not loaded: " + e.getMessage());
}
}
public static boolean isLibraryLoaded() {
return libraryLoaded;
}
public static native int SDF_OpenDevice(int dwDeviceType, byte[] pDeviceName, int[] pdwDeviceNameLen);
public static native int SDF_CloseDevice(int hDevice);
public static native int SDF_OpenSession(int hDevice, int dwAppType, byte[] pAppID, int dwAppIDLen, int[] phSession);
public static native int SDF_CloseSession(int hSession);
public static native int SDF_GetDeviceInfo(int hSession, SdfDeviceInfo pDeviceInfo);
}

View File

@ -0,0 +1,41 @@
package com.sunyard.cisd;
import java.nio.ByteBuffer;
public class SdfDeviceInfo {
public byte[] issuerName = new byte[40];
public byte[] deviceName = new byte[40];
public byte[] deviceSerial = new byte[40];
public int deviceVersion;
public int standardVersion;
public int asymAlgAbility[] = new int[2];
public int symAlgAbility;
public int hashAlgAbility;
public int bufferSize;
public void read() {
}
public String getIssuerName() {
return zeroTerminatedString(issuerName);
}
public String getDeviceName() {
return zeroTerminatedString(deviceName);
}
public String getDeviceSerial() {
return zeroTerminatedString(deviceSerial);
}
private String zeroTerminatedString(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return "";
}
int len = 0;
while (len < bytes.length && bytes[len] != 0) {
len++;
}
return new String(bytes, 0, len).trim();
}
}