根據機器的CPU、主板、MAC地址生成唯一的激活碼,授權認證
參考了網上許多博客,文章,最後總結出來。
https://github.com/Dagon0577/Dagon_Code
Dagon_Code
從Windows,Linux獲取CPU,主板,MAC地址,虛擬ID(docker,machine-rkt),並生成Dagon_Code。
判斷是否爲虛擬機或者容器
首先判斷是否爲虛擬機或者是容器,若不是,再去物理機下獲取。(相關方法在下文)
/**
* 判斷是否爲容器、虛擬機,返回虛擬ID
*
* @return
*/
public static String getVirtualID() {
String execResult = executeLinuxCmd("systemd-detect-virt");
if (!execResult.contains("none")) {
//docker容器
String VirtualID = getSerialNumber("cat /proc/1/cgroup", "docker", "docker/");
if (VirtualID != null) {
return VirtualID;
}
//machine-rkt
VirtualID = getSerialNumber("cat /proc/1/cgroup", "machine-rkt", "machine-rkt\\");
if (VirtualID != null) {
VirtualID.replaceAll("\\x2d", "-");
return VirtualID;
}
//vmware
VirtualID = getSerialNumber("dmidecode -t system", "UUID", ":");
if (VirtualID != null) {
return VirtualID;
}
return "UNKNOWN";
}
return null;
}
Windows下
通過創建vbs腳本,然後使用Runtime.getRuntime().exec()執行腳本,獲取序列號等信息。
獲取CPU序列號
/**
* 獲取CPU序列號
*
* @return
*/
public static String getCPUSerial() {
String result = "";
try {
File file = File.createTempFile("tmp", ".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);
String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+ "Set colItems = objWMIService.ExecQuery _ \n"
+ " (\"Select * from Win32_Processor\") \n"
+ "For Each objItem in colItems \n" + " Wscript.Echo objItem.ProcessorId \n"
+ " exit for ' do the first cpu only! \n" + "Next \n";
// + " exit for \r\n" + "Next";
fw.write(vbs);
fw.close();
String path = file.getPath().replace("%20", " ");
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + path);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
result += line;
}
input.close();
file.delete();
} catch (Exception e) {
e.fillInStackTrace();
}
if (result.trim().length() < 1 || result == null) {
result = "無CPU_ID被讀取";
}
return result.trim();
}
獲取主板序列號
/**
* 獲取主板序列號
*
* @return
*/
public static String getMotherboardSN() {
String result = "";
try {
File file = File.createTempFile("realhowto", ".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);
String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+ "Set colItems = objWMIService.ExecQuery _ \n"
+ " (\"Select * from Win32_BaseBoard\") \n"
+ "For Each objItem in colItems \n" + " Wscript.Echo objItem.SerialNumber \n"
+ " exit for ' do the first cpu only! \n" + "Next \n";
fw.write(vbs);
fw.close();
String path = file.getPath().replace("%20", " ");
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + path);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
result += line;
}
input.close();
} catch (Exception e) {
e.printStackTrace();
}
return result.trim();
}
獲取本機所有MAC地址信息
/**
* MAC
* 通過jdk自帶的方法,先獲取本機所有的ip,然後通過NetworkInterface獲取mac地址
*
* @return
*/
public static String getMac() {
try {
String resultStr = "";
List<String> ls = getLocalHostLANAddress();
int num = 0;
for (String str : ls) {
InetAddress ia = InetAddress.getByName(str);// 獲取本地IP對象
// 獲得網絡接口對象(即網卡),並得到mac地址,mac地址存在於一個byte數組中。
byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
// 下面代碼是把mac地址拼裝成String
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
if (i != 0) {
sb.append("-");
}
// mac[i] & 0xFF 是爲了把byte轉化爲正整數
String s = Integer.toHexString(mac[i] & 0xFF);
sb.append(s.length() == 1 ? 0 + s : s);
}
if (num == ls.size() - 1) {
resultStr += sb.toString().toUpperCase();
} else {
// 把字符串所有小寫字母改爲大寫成爲正規的mac地址並返回
resultStr += sb.toString().toUpperCase() + ",";
}
num++;
}
return resultStr;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
Linux下
Linux同樣使用Runtime.getRuntime().exec()執行Linux命令,獲取相關信息。
執行命令
public static String executeLinuxCmd(String cmd) {
try {
System.out.println("got cmd job : " + cmd);
Runtime run = Runtime.getRuntime();
Process process;
process = run.exec(cmd);
InputStream in = process.getInputStream();
BufferedReader bs = new BufferedReader(new InputStreamReader(in));
StringBuffer out = new StringBuffer();
byte[] b = new byte[8192];
for (int n; (n = in.read(b)) != -1; ) {
out.append(new String(b, 0, n));
}
in.close();
process.destroy();
return out.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
執行命令後獲取信息
/**
* @param cmd 命令語句
* @param record 要查看的字段
* @param symbol 分隔符
* @return
*/
public static String getSerialNumber(String cmd, String record, String symbol) {
String execResult = executeLinuxCmd(cmd);
String[] infos = execResult.split("\n");
for (String info : infos) {
info = info.trim();
if (info.indexOf(record) != -1) {
info.replace(" ", "");
String[] sn = info.split(symbol);
return sn[1];
}
}
return null;
}
/**
* @param cmd 命令語句
* @param record 要查看的字段
* @param symbol 分隔符
* @return
*/
public static String getAllSerialNumber(String cmd, String record, String symbol) {
String execResult = executeLinuxCmd(cmd);
String[] infos = execResult.split("\n");
StringBuilder result = new StringBuilder();
int k = 0;
for (int i = 0; i < infos.length - 1; i++) {
String info = infos[i];
info = info.trim();
if (info.indexOf(record) != -1) {
info.replace(" ", "");
String[] sn = info.split(symbol);
if (k != 0) {
result.append(',');
}
result.append(sn[1]);
k++;
}
}
if (k != 0) {
return result.toString();
} else {
return null;
}
}
根據獲取的機器信息,生成唯一的激活碼。
激活碼生成策略
加密算法介紹
SHA1
是一種流行的消息摘要算法,跟MD5
相比,SHA1
比MD5
的 安全性更強。對於長度小於 2 ^ 64 位的消息,SHA1
會產生一個160位的消息摘要。基於MD5
、SHA1
的信息摘要特性以及不可逆 (一般而言),可以被應用在檢查文件完整性
以及數字簽名
等場景。Blowfish
算法是著名的對稱加密算法,是一種將64位數據分組及使用可變長度密鑰的對稱密鑰分組加密算法,可用來加密64位長度的字符串。32位處理器誕生後,Blowfish
算法因其在加密速度上的優越性而引起人們的廣泛關注。Blowfish
算法具有加密速度快、緊湊、密鑰長度可變、免費使用等特點,已被廣泛使用於軟件保護、軟件認證激活。算法核心在於子密鑰的生成,它將變長密鑰擴展成總長4168 比特位的子密鑰數組。算法中使用了大量的子密鑰,而子密鑰又依賴於用戶密鑰,實際加密解密過程中使用的是更新後的子密鑰數組,子密鑰即P數組和S盒。算法輸人64位明文信息,經過加密運算,輸出64位密文信息。
加密方案設計
Dagon_Code將混合使用上述兩種加密算法,設計設計一種新型的、高效的、破解難度高的混合加密方案,以增強安全性。加密方案核心步驟如下:
-
1.對原始信息資源使用SHA1算法進行加密,產生128位散列值;
-
2.將步驟1產生的固定長度散列值作爲Blowfish算法的用戶密鑰,初始化Blowfish加密算法;
-
3.使用初始化完成後的Blowfish算法對原始信息資源的進行加密,加密後即會產生高安全性的密文數據。
具體代碼實現
https://github.com/Dagon0577/Dagon_Code