Search Here

Custom Search

Tuesday, August 19, 2008

Generating Unique Key(Finger Print) for a Computer for Licensing Purpose


Download the complete source code.


Introduction

For licensing purpose according to me the best way and secure way is to generate an unique key for client's machine and providing a corresponding license key for that key. For this purpose you can take help of the unique id of client's computer's motherboard, BIOS and processor's. When you get these IDs you can generate any key of your preferable format.

Year ago I found a very handy and useful code in C# by searching net to get these IDs. And its serving me perfectly so far. Thanks to the original author of the code.

I added some additional code to generate a 128 bit key of a machine. The output is a nice looking key in hexadecimal format (eg. 4876-8DB5-EE85-69D3-FE52-8CF7-395D-2EA9)

Suggestions

I have few suggestions on this regard.

*) Generate key from only Motherboard, Processor and BIOS. Since user normally doesn't chagne these parts.

*) Don't use MAC ID, Graphics Card ID AND Disk ID. Since its very common to change these devices.

*) It takes significant time to get IDs of devices. So make the finger print generating fucntion static and save it in a static variable so that it generates the key only for one time in the whole application.

The Code

Here is the class. The code in the region "Original Device ID Getting Code" is from the original author.



using System;
using System.Management;
using System.Security.Cryptography;
using System.Security;
using System.Collections;
using System.Text;
namespace Security
{
/// <summary>
/// Generates a 16 byte Unique Identification code of a computer
/// Example: 4876-8DB5-EE85-69D3-FE52-8CF7-395D-2EA9
/// </summary>
public class FingerPrint
{
private static string fingerPrint = string.Empty;
public static string Value()
{
if (string.IsNullOrEmpty(fingerPrint))
{
fingerPrint = GetHash("CPU >> " + cpuId() + "\nBIOS >> " + biosId() + "\nBASE >> " + baseId()
//+"\nDISK >> "+ diskId() + "\nVIDEO >> " + videoId() +"\nMAC >> "+ macId()
);
}
return fingerPrint;
}
private static string GetHash(string s)
{
MD5 sec = new MD5CryptoServiceProvider();
ASCIIEncoding enc = new ASCIIEncoding();
byte[] bt = enc.GetBytes(s);
return GetHexString(sec.ComputeHash(bt));
}
private static string GetHexString(byte[] bt)
{
string s = string.Empty;
for (int i = 0; i < bt.Length; i++)
{
byte b = bt[i];
int n, n1, n2;
n = (int)b;
n1 = n & 15;
n2 = (n >> 4) & 15;
if (n2 > 9)
s += ((char)(n2 - 10 + (int)'A')).ToString();
else
s += n2.ToString();
if (n1 > 9)
s += ((char)(n1 - 10 + (int)'A')).ToString();
else
s += n1.ToString();
if ((i + 1) != bt.Length && (i + 1) % 2 == 0) s += "-";
}
return s;
}
#region Original Device ID Getting Code
//Return a hardware identifier
private static string identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue)
{
string result = "";
System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
System.Management.ManagementObjectCollection moc = mc.GetInstances();
foreach (System.Management.ManagementObject mo in moc)
{
if (mo[wmiMustBeTrue].ToString() == "True")
{
//Only get the first one
if (result == "")
{
try
{
result = mo[wmiProperty].ToString();
break;
}
catch
{
}
}
}
}
return result;
}
//Return a hardware identifier
private static string identifier(string wmiClass, string wmiProperty)
{
string result = "";
System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
System.Management.ManagementObjectCollection moc = mc.GetInstances();
foreach (System.Management.ManagementObject mo in moc)
{
//Only get the first one
if (result == "")
{
try
{
result = mo[wmiProperty].ToString();
break;
}
catch
{
}
}
}
return result;
}
private static string cpuId()
{
//Uses first CPU identifier available in order of preference
//Don't get all identifiers, as very time consuming
string retVal = identifier("Win32_Processor", "UniqueId");
if (retVal == "") //If no UniqueID, use ProcessorID
{
retVal = identifier("Win32_Processor", "ProcessorId");
if (retVal == "") //If no ProcessorId, use Name
{
retVal = identifier("Win32_Processor", "Name");
if (retVal == "") //If no Name, use Manufacturer
{
retVal = identifier("Win32_Processor", "Manufacturer");
}
//Add clock speed for extra security
retVal += identifier("Win32_Processor", "MaxClockSpeed");
}
}
return retVal;
}
//BIOS Identifier
private static string biosId()
{
return identifier("Win32_BIOS", "Manufacturer")
+ identifier("Win32_BIOS", "SMBIOSBIOSVersion")
+ identifier("Win32_BIOS", "IdentificationCode")
+ identifier("Win32_BIOS", "SerialNumber")
+ identifier("Win32_BIOS", "ReleaseDate")
+ identifier("Win32_BIOS", "Version");
}
//Main physical hard drive ID
private static string diskId()
{
return identifier("Win32_DiskDrive", "Model")
+ identifier("Win32_DiskDrive", "Manufacturer")
+ identifier("Win32_DiskDrive", "Signature")
+ identifier("Win32_DiskDrive", "TotalHeads");
}
//Motherboard ID
private static string baseId()
{
return identifier("Win32_BaseBoard", "Model")
+ identifier("Win32_BaseBoard", "Manufacturer")
+ identifier("Win32_BaseBoard", "Name")
+ identifier("Win32_BaseBoard", "SerialNumber");
}
//Primary video controller ID
private static string videoId()
{
return identifier("Win32_VideoController", "DriverVersion")
+ identifier("Win32_VideoController", "Name");
}
//First enabled network card ID
private static string macId()
{
return identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled");
}
#endregion
}
}

Upcoming Code

Later I'll show how I generated the license key from the unique machine key. The license key contains many information like the Product Name, License Start Date, End Date and the Key.


Download the complete source code.

18 comments:

cocis said...

Sowkot,

Great way to find the serial numbers, thanks for the code
I was looking the way to read some serial numbers, the hard drive serail number, I find out that the HD serial number can be clone.

Very cool

Sowkot said...

Thanks for your comment, Cocis.

Raymond said...

Nice code! very usefull.. can you show the rest (how to get the licence key etc)?

jreinap said...

Really fantastic!

When you will have the upcoming code?

achaemenianboy said...

hi
i am need to Decode FingerPrint.Value() result and get bios information , cpu information and etc.
please help me.
thanks.

jagagid said...

how to achieve the same using asp.net. I want the client machines code using asp.net. I tried out the same code. But it is getting me the hosted server machines hardware id rather than Client machine Id.

Please suggest.

StormySeaSailor said...

I already saw the original code but your changes are great !
It's true that some hardware parts change a lot ... also with the same hardware the VideoId() was giving me different values depending on how the code was called (video drivers would change ?).

Note: the hash makes the serial look more professional however a hash is not unique. The chances are damn small but theoretically two different machines could generate the same key ... anyway I'm still going with it ;-)

Shohag_ifas said...

hi, brother thanks for nice sharing...

but my coding language is vb6 so, it's no use to me.. but i need this.. to.. much..

can you make it a dll file what can be access/called from vb 6?

please brother leave a reply asap at altufaltu.sb@gmail.com

Seguridad Informática said...

I found the concept responding superbly to my needs.

I do programming in C and some C++ and would appreciate any help you provide for providing converting information to C or C++ for Linux and for Windows.

Seguridad Informática said...

I found the concept responding superbly to my needs.

I do programming in C and some C++ and would appreciate any help you provide for providing converting information to C or C++ for Linux and for Windows.

Manish Kumar said...

How to get disk identification number in case of GPT partition style. Since signature becomes NULL for this case.

Cool Brezze said...

thanks but i need equivalent in vb6

Cool Brezze said...

merci pour ta solution mais je developpe en vb6 stp u pourai m'envoyer l'equivalent en vb6 avec un peu plus d'explication sur comment l'utiliser

Morpheus said...

"Later I'll show how I generated the license key from the unique machine key. The license key contains many information like the Product Name, License Start Date, End Date and the Key."

So when are you going to do this I would like to see it.

Tushar Jagdale said...

Hi , all code is nice...
but what is the "Management class" , i receive these errors==>
"The type or namespace name 'ManagementClass' does not exist in the namespace 'System.Management' "

Zobayer Hasan said...

@Tushar Jagdale
You need to manually add System.Management as a Reference. Just "using" is not enough.

cgb1776 said...

This code is great! Could really use the info on how to create the license key.

Aubin Thomas said...

Absolutely fantastic. When will you be explaining on how to create license keys.