Skip to content

Commit f3adb60

Browse files
committed
Update machine code method
1 parent d289d9e commit f3adb60

File tree

4 files changed

+243
-2
lines changed

4 files changed

+243
-2
lines changed

.idea/.gitignore

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/io/cryptolens/legacy/HttpsURLConnectionRequestHandler.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.cryptolens.legacy;
22

33
import io.cryptolens.internal.HelperMethods;
4-
import sun.net.util.URLUtil;
54

65
import java.io.*;
76
import java.net.*;

src/main/java/io/cryptolens/methods/Helpers.java

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@
1616
import java.io.IOException;
1717
import java.io.InputStreamReader;
1818
import java.nio.charset.StandardCharsets;
19+
import java.nio.file.Files;
20+
import java.nio.file.Path;
21+
import java.nio.file.Paths;
1922
import java.security.MessageDigest;
23+
import java.util.Locale;
24+
import java.util.regex.Matcher;
25+
import java.util.regex.Pattern;
2026

2127

2228
/**
@@ -59,6 +65,10 @@ public static String GetMachineCode(int v) {
5965
return GetMachineCode();
6066
}
6167

68+
if(v== 3) {
69+
return getMachineCode_v3();
70+
}
71+
6272
String operSys = System.getProperty("os.name").toLowerCase();
6373

6474
if (operSys.contains("win")) {
@@ -108,6 +118,43 @@ public static String GetMachineCode(int v) {
108118

109119
}
110120

121+
private static String getMachineCode_v3() {
122+
final String operSys = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
123+
124+
try {
125+
String seed = null;
126+
127+
if (operSys.contains("win")) {
128+
seed = getWindowsUUID();
129+
130+
} else if (operSys.contains("mac")) {
131+
seed = getMacHardwareUUID();
132+
133+
} else if (operSys.contains("nix") || operSys.contains("nux")
134+
|| operSys.contains("aix") || operSys.contains("linux")) {
135+
seed = getLinuxMachineSeed();
136+
137+
} else {
138+
return "This OS is not supported yet.";
139+
}
140+
141+
if (seed == null) {
142+
return null;
143+
}
144+
145+
seed = seed.trim();
146+
if (seed.isEmpty()) {
147+
return null;
148+
}
149+
150+
return sha256(seed);
151+
152+
} catch (Exception e) {
153+
// Swallow to preserve current behavior; consider logging in real apps
154+
return null;
155+
}
156+
}
157+
111158
/**
112159
* Check if the device is registered with the license key.
113160
* @param license The license key object.
@@ -448,4 +495,194 @@ private static String getRawDeviceID()
448495
processors;
449496
}
450497

498+
499+
/* =========================
500+
Windows
501+
========================= */
502+
private static String getWindowsUUID() throws IOException, InterruptedException {
503+
// Primary: PowerShell CIM
504+
String out = run(new ProcessBuilder(
505+
"powershell.exe", "-NoProfile", "-NonInteractive",
506+
"-Command", "(Get-CimInstance -Class Win32_ComputerSystemProduct).UUID"));
507+
out = firstNonEmptyLine(out);
508+
if (isLikelyUUID(out)) {
509+
return out;
510+
}
511+
512+
// Fallback: WMIC (deprecated on newer Windows but still present on many)
513+
out = run(new ProcessBuilder("wmic", "csproduct", "get", "UUID"));
514+
// WMIC outputs a header line "UUID" and then the value—pick the first line that looks like a UUID
515+
for (String line : out.split("\\R")) {
516+
line = line.trim();
517+
if (isLikelyUUID(line)) return line;
518+
}
519+
return null;
520+
}
521+
522+
/* =========================
523+
macOS
524+
========================= */
525+
private static String getMacHardwareUUID() throws IOException, InterruptedException {
526+
// Matches: "Hardware UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
527+
String cmd = "system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }'";
528+
String out = runShell(cmd);
529+
out = firstNonEmptyLine(out);
530+
if (isLikelyUUID(out)) {
531+
return out;
532+
}
533+
534+
// Optional fallback using ioreg, if needed
535+
String alt = runShell("ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ {print $4}' | tr -d '\"'");
536+
alt = firstNonEmptyLine(alt);
537+
return isLikelyUUID(alt) ? alt : null;
538+
}
539+
540+
/* =========================
541+
Linux
542+
========================= */
543+
private static String getLinuxMachineSeed() throws IOException, InterruptedException {
544+
// 1) Raspberry Pi detection via /proc/device-tree/model (present on Pi; often missing in VMs/containers)
545+
String model = readFileIfExists("/proc/device-tree/model");
546+
if (model == null) {
547+
// Some environments need this alt path or may deny access to device-tree; not fatal.
548+
model = readFileIfExists("/sys/firmware/devicetree/base/model");
549+
}
550+
if (model != null && model.toLowerCase(Locale.ENGLISH).contains("raspberry")) {
551+
// Extract "Serial" from /proc/cpuinfo
552+
String cpuinfo = readFileIfExists("/proc/cpuinfo");
553+
if (cpuinfo != null) {
554+
for (String line : cpuinfo.split("\\R")) {
555+
String t = line.trim();
556+
if (t.toLowerCase(Locale.ENGLISH).startsWith("serial")) {
557+
String[] parts = t.split(":", 2);
558+
if (parts.length == 2) {
559+
String serial = parts[1].trim();
560+
if (!serial.isEmpty()) return serial;
561+
}
562+
}
563+
}
564+
}
565+
// If Pi but serial not found, continue to the generic path
566+
}
567+
568+
// 2) Generic Linux: try DMI product UUID (no sudo required on many distros)
569+
String dmi = readFileIfExists("/sys/class/dmi/id/product_uuid");
570+
if (dmi != null) {
571+
dmi = firstNonEmptyLine(dmi);
572+
if (isLikelyUUID(dmi)) return dmi;
573+
}
574+
575+
// 3) dmidecode (requires permissions; often needs sudo — will work in privileged envs)
576+
String dmiDecode = runMaybe(null, new ProcessBuilder("dmidecode", "-s", "system-uuid"));
577+
dmiDecode = firstNonEmptyLine(dmiDecode);
578+
if (isLikelyUUID(dmiDecode)) return dmiDecode;
579+
580+
// 4) Your specified fallback when we cannot determine hardware:
581+
// Try UUID of /boot, then /boot/efi, then /
582+
String fsUuid = firstNonEmptyLine(runShell("findmnt --output=UUID --noheadings --target=/boot"));
583+
if (fsUuid == null || fsUuid.isEmpty()) {
584+
fsUuid = firstNonEmptyLine(runShell("findmnt --output=UUID --noheadings --target=/boot/efi"));
585+
}
586+
if (fsUuid == null || fsUuid.isEmpty()) {
587+
fsUuid = firstNonEmptyLine(runShell("findmnt --output=UUID --noheadings --target=/"));
588+
}
589+
if (fsUuid != null && !fsUuid.isEmpty()) {
590+
return fsUuid;
591+
}
592+
593+
// 5) Last-resort for containerized / exotic hosts: OS installation id (not hardware!)
594+
String machineId = readFileIfExists("/etc/machine-id");
595+
if (machineId == null) {
596+
machineId = readFileIfExists("/var/lib/dbus/machine-id");
597+
}
598+
machineId = firstNonEmptyLine(machineId);
599+
if (machineId != null && !machineId.isEmpty()) {
600+
return machineId;
601+
}
602+
603+
return null;
604+
}
605+
606+
/* =========================
607+
Helpers
608+
========================= */
609+
610+
private static String runShell(String command) throws IOException, InterruptedException {
611+
// Use /bin/sh for portability across macOS and Linux
612+
return run(new ProcessBuilder("/bin/sh", "-c", command));
613+
}
614+
615+
private static String run(ProcessBuilder pb) throws IOException, InterruptedException {
616+
pb.redirectErrorStream(true);
617+
Process p = pb.start();
618+
StringBuilder sb = new StringBuilder();
619+
try (BufferedReader in = new BufferedReader(
620+
new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
621+
String line;
622+
while ((line = in.readLine()) != null) {
623+
if (sb.length() > 0) sb.append('\n');
624+
sb.append(line);
625+
}
626+
}
627+
// Wait after draining streams to avoid deadlocks.
628+
p.waitFor();
629+
return sb.toString().trim();
630+
}
631+
632+
private static String runMaybe(String defaultIfError, ProcessBuilder pb) {
633+
try {
634+
return run(pb);
635+
} catch (Exception e) {
636+
return defaultIfError;
637+
}
638+
}
639+
640+
private static String readFileIfExists(String path) {
641+
try {
642+
Path p = Paths.get(path);
643+
if (!Files.exists(p)) return null;
644+
// Some files (like device-tree nodes) may contain NULs; read as bytes then clean
645+
byte[] bytes = Files.readAllBytes(p);
646+
String s = new String(bytes, StandardCharsets.UTF_8).replace("\u0000", "");
647+
return s.trim();
648+
} catch (Exception e) {
649+
return null;
650+
}
651+
}
652+
653+
private static String firstNonEmptyLine(String text) {
654+
if (text == null) return null;
655+
for (String line : text.split("\\R")) {
656+
line = line.trim();
657+
if (!line.isEmpty()) return line;
658+
}
659+
return null;
660+
}
661+
662+
private static boolean isLikelyUUID(String s) {
663+
if (s == null) return false;
664+
String t = s.trim();
665+
// Accept canonical UUIDs and common uppercase variants
666+
Pattern p = Pattern.compile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$");
667+
Matcher m = p.matcher(t);
668+
if (m.matches()) return true;
669+
// Some firmware returns UUIDs without dashes; tolerate that too
670+
return t.matches("^[a-fA-F0-9]{32}$");
671+
}
672+
673+
private static String sha256(String input) {
674+
try {
675+
MessageDigest md = MessageDigest.getInstance("SHA-256");
676+
byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
677+
StringBuilder hex = new StringBuilder(digest.length * 2);
678+
for (byte b : digest) {
679+
hex.append(Character.forDigit((b >>> 4) & 0xF, 16));
680+
hex.append(Character.forDigit(b & 0xF, 16));
681+
}
682+
return hex.toString();
683+
} catch (Exception e) {
684+
return null;
685+
}
686+
}
687+
451688
}

src/test/java/io/cryptolens/HelpersTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public void testApp()
7272

7373
public void testMachineCode() throws IOException {
7474

75-
Helpers.GetMachineCode();
75+
//Helpers.GetMachineCode();
7676

7777
String mc = Helpers.GetMachineCode(2);
7878

@@ -86,6 +86,8 @@ public void testMachineCode() throws IOException {
8686

8787
assertTrue(Helpers.IsOnRightMachine(license, 2));
8888

89+
String a = Helpers.getMachineCodev3();
90+
System.out.println(a);
8991

9092

9193
}

0 commit comments

Comments
 (0)