Pages

Sunday, November 11, 2012

How to get unique hardware id

If you write something like licensing for your application, you definitely will think to get the unique hardware id to bind your key to PC. So overral your scheme would look like this:

  • Generation of the code on the clients PC;
  • Getting that code to license generator;
  • Some manupilations with that code;
  • Sending resulting key to the client;
  • Check license key with every run of the clients application.

The simples implementation would be generation of the code based on hardware. It can be easily done with WMI (Windows management instrumentation). The simplest method would be to use processor id, like this:

public static string GetProcessorId()
{
    string processorID;
    var searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_Processor");

    foreach (ManagementObject queryObj in searcher.Get())
    {
        processorID = queryObj["ProcessorId"]).ToString();
    }
    return processorID;
}

It would give you something like this: "BFEBFBFF000206A7".
There are also other options from WMI. You could use:

Dictionary<string, string> IDs = new Dictionary<string, string>();

//MotherBoard
searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM CIM_Card");
foreach (ManagementObject queryObj in searcher.Get())
    IDs.Add("CardID", queryObj["SerialNumber"].ToString());

//OS
searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM CIM_OperatingSystem");
foreach (ManagementObject queryObj in searcher.Get())
    IDs.Add("OSSerialNumber", queryObj["SerialNumber"].ToString());

//Keyboard. I am not really sure if is is a good idea - to bind to keyboard...
searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM CIM_KeyBoard");
foreach (ManagementObject queryObj in searcher.Get())
    IDs.Add("KeyBoardID", queryObj["DeviceId"].ToString());

//Mouse. It is also not the most stable part of the hardware...
searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_PointingDevice");
foreach (ManagementObject queryObj in searcher.Get())
    IDs.Add("MouseID", queryObj["DeviceID"].ToString());

//SoundCard
searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_SoundDevice");
foreach (ManagementObject queryObj in searcher.Get())
    IDs.Add("SoundCardID", queryObj["DeviceID"].ToString());

//UUID
searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT UUID FROM Win32_ComputerSystemProduct");
foreach (ManagementObject queryObj in searcher.Get())
    IDs.Add("UUID", queryObj["UUID"].ToString());

So there are plenty of options and if you want to bind not only to a single component, you can use hashing, for example:

private static string GetUniqueHardwaeId()
{
  var sb = new StringBuilder();

  var searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_Processor");
  foreach (ManagementObject queryObj in searcher.Get())
  {
    sb.Append(queryObj["NumberOfCores"]);
    sb.Append(queryObj["ProcessorId"]);
    sb.Append(queryObj["Name"]);
    sb.Append(queryObj["SocketDesignation"]);
  }

  var bytes = Encoding.UTF8.GetBytes(sb.ToString());
  var sha = new System.Security.Cryptography.SHA256Managed();

  byte[] hash = sha.ComputeHash(bytes);
  return BitConverter.ToString(hash);
}

No comments:

Post a Comment