1 /// Hardware identifiers (HWID) and processor features. 2 module tern.os.identifiers; 3 4 import tern.string; 5 import tern.digest; 6 import tern.digest.sha; 7 version (Windows) 8 { 9 import std.windows.registry; 10 } 11 else version (linux) 12 { 13 import std.process; 14 import std.file; 15 import std.stdio : lines; 16 } 17 18 public: 19 static: 20 // This implementation is not fast, but neither are most hwid extractions \_( -.-)_/ 21 version (Windows) 22 { 23 /// Retrieves the motherboard serial number. May fail and return null. 24 string moboSerial() 25 { 26 try 27 { 28 Key hKey = Registry.localMachine.getKey(r"SYSTEM\HardwareConfig"); 29 return hKey.getValue("LastConfig").value_SZ.toLower()[1..$-1]; 30 } 31 catch (RegistryException ex) 32 { 33 34 } 35 36 try 37 { 38 Key hKey = Registry.users.getKey(r".DEFAULT\Software\Microsoft\Office\Common\ClientTelemetry"); 39 return hKey.getValue("MotherboardUUID").value_SZ.toLower()[1..$-1]; 40 } 41 catch (RegistryException ex) 42 { 43 44 } 45 46 try 47 { 48 Key hKey = Registry.currentUser.getKey(r"Software\Microsoft\Office\Common\ClientTelemetry"); 49 return hKey.getValue("MotherboardUUID").value_SZ.toLower()[1..$-1]; 50 } 51 catch (RegistryException ex) 52 { 53 return null; 54 } 55 } 56 57 /// Retrieves the monitor serial number. May fail and return null. 58 string monitorSerial() 59 { 60 try 61 { 62 Key hKey = Registry.localMachine.getKey(r"SYSTEM\CurrentControlSet\Enum\DISPLAY\"); 63 hKey = hKey.keys[0]; 64 hKey = hKey.keys[0]; 65 hKey = hKey.keys[0]; 66 return digest!SHA1(cast(ubyte[])hKey.getValue("EDID").value_BINARY).toHexString().toLower(); 67 } 68 catch (RegistryException ex) 69 { 70 return null; 71 } 72 } 73 74 /// Retrieves the disk serial number. May fail and return null. 75 string diskSerial() 76 { 77 try 78 { 79 Key hKey = Registry.localMachine.getKey(r"HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0"); 80 return hKey.getValue("SerialNumber").value_SZ.toLower(); 81 } 82 catch (RegistryException ex) 83 { 84 85 } 86 87 try 88 { 89 Key hKey = Registry.localMachine.getKey(r"HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\DiskController\0\DiskPeripheral"); 90 hKey = hKey.keys[0]; 91 return hKey.getValue("Identifier").value_SZ.toLower(); 92 } 93 catch (RegistryException ex) 94 { 95 return null; 96 } 97 } 98 99 /// Retrieves the sum SMBios serial number. May fail and return null. 100 string biosSerial() 101 { 102 try 103 { 104 Key hKey = Registry.localMachine.getKey(r"SYSTEM\CurrentControlSet\Services\mssmbios\Data"); 105 byte[] table = hKey.getValue("AcpiData").value_BINARY~hKey.getValue("BiosData").value_BINARY~ 106 hKey.getValue("RegistersData").value_BINARY~hKey.getValue("SMBiosData").value_BINARY; 107 return digest!SHA1(cast(ubyte[])table).toHexString().toLower(); 108 } 109 catch (RegistryException ex) 110 { 111 return null; 112 } 113 } 114 115 /// Summation of all serials hashes into a single hardware id. Could be an invalid identifier but unlikely. 116 string hardwareId() 117 { 118 ubyte[] serials = cast(ubyte[])moboSerial()~cast(ubyte[])monitorSerial()~cast(ubyte[])diskSerial()~cast(ubyte[])biosSerial(); 119 return digest!SHA1(serials).toHexString().toLower(); 120 } 121 } 122 else version (linux) 123 { 124 /// Retrieves the motherboard serial number. Will never return null. 125 string moboSerial() 126 { 127 return readText(r"/sys/class/dmi/id/board_serial"); 128 } 129 130 /// Retrieves the chassis serial number. Will never return null. 131 string chassisSerial() 132 { 133 return readText(r"/sys/class/dmi/id/chassis_serial"); 134 } 135 136 /// Retrieves the disk serial number. May fail and return null. 137 string diskSerial() 138 { 139 auto process = pipeProcess("lsblk -no serial", Redirect.stdout); 140 wait(process.pid); 141 foreach (string line; lines(process.stdout)) 142 { 143 if (!line.length) continue; 144 return line; 145 } 146 return null; 147 } 148 149 /// Summation of all serials hashes into a single hardware id. Could be an invalid identifier but unlikely. 150 string hardwareId() 151 { 152 ubyte[] serials = cast(ubyte[])moboSerial()~cast(ubyte[])chassisSerial()~cast(ubyte[])diskSerial(); 153 return digest!SHA1(serials).toHexString().toLower(); 154 } 155 }