Support
Joined: 18 Jul 2005 Posts: 731
|
Posted: Tue Aug 18, 2009 5:05 am Post subject: CODE: Sample CryptoLicense.IsMachineCodeValid implementation |
|
|
When a machine-locked is being validated, it byte-compares the machine code embedded in the license with the code returned by the GetLocalMachineCode method. To have more control over this, override the CryptoLicense.IsMachineCodeValid method. This can be useful when you want to implement a somewhat lenient machine code comparison method instead of the default strict byte-comparison. For example, your machine code could consist of a combination of the CPU-ID, BIOS serial number, amount of memory, hard-disk serial number and the MAC address. You may want to allow one or more components of the machine code to change so that every small hardware change does not make the license invalid. The following code demonstrates this:
[C#]
Code: |
public class CustomCryptoLicense : CryptoLicense
{
// Override to provide custom machine code
// This example uses a combo of the CPU-ID and motherboard serial as the machine code
// The machine is considered matched if either of the two match
public override byte[] GetLocalMachineCode()
{
byte[] ret = null;
try
{
ret = CombineBuffersWithLength(GetCPUId(), GetMBSerial());
}
catch { }
// Fall back to base implementation if failed
if(ret==null || ret.Length==2)
ret = base.GetLocalMachineCode();
return ret;
}
public override bool IsMachineCodeValid()
{
try
{
byte[] embeddedMachineCode = this.MachineCode;
byte[] localMachineCode = this.GetLocalMachineCode();
byte[] cpuid1, cpuid2, mbserial1, mbserial2;
if (SplitBuffer(embeddedMachineCode, out cpuid1, out mbserial1) && SplitBuffer(localMachineCode, out cpuid2, out mbserial2))
{
// Consider valid of either cpu-id or mb-serial matches
if (AreBuffersEqual(cpuid1, cpuid2) || AreBuffersEqual(mbserial1, mbserial2))
return true;
else
return false;
}
}
catch { }
// Fall back to base implementation if failed
return base.IsMachineCodeValid();
}
// Gets the CPU-ID of the local machine
static internal byte[] GetCPUId()
{
try
{
ManagementClass mgmt = new ManagementClass("Win32_Processor");
ManagementObjectCollection objCol = mgmt.GetInstances();
foreach (ManagementObject obj in objCol)
{
// Only use CPU-ID from the first CPU
string cpuInfo = obj.Properties["ProcessorId"].Value.ToString();
if (cpuInfo != null && cpuInfo.Length > 0)
{
byte[] ret = Encoding.UTF8.GetBytes(cpuInfo);
return ret;
}
}
}
catch { }
return new byte[0];
}
static internal byte[] GetMBSerial()
{
try
{
ManagementClass mgmt = new ManagementClass("Win32_BaseBoard");
ManagementObjectCollection objCol = mgmt.GetInstances();
foreach (ManagementObject obj in objCol)
{
// Only use CPU-ID from the first CPU
string mbserial = obj.Properties["SerialNumber"].Value.ToString();
if (mbserial != null && mbserial.Length > 0)
{
byte[] ret = Encoding.UTF8.GetBytes(mbserial);
return ret;
}
}
}
catch { }
return new byte[0];
}
static byte[] CombineBuffersWithLength(byte[] buff1, byte[] buff2)
{
// Returned format is:
// buff1length-....buff1....-buff2length-...buff2....
byte[] ret = new byte[buff1.Length + buff2.Length + 2];
ret[0] = (byte)buff1.Length;
buff1.CopyTo(ret, 1);
ret[buff1.Length + 1] = (byte)buff2.Length;
buff2.CopyTo(ret, buff1.Length + 2);
return ret;
}
static bool AreBuffersEqual(byte[] buff1,byte[] buff2)
{
try
{
if (buff1.Length != buff2.Length)
return false;
for (int i = 0; i < buff1.Length; i++)
{
if (buff1[i] != buff2[i])
return false;
}
return true;
}
catch { }
return false;
}
// Gets machine code components
static bool SplitBuffer(byte[] buff, out byte[] buff1, out byte[] buff2)
{
buff1 = buff2 = null;
try
{
byte buff1Length = buff[0];
buff1 = new byte[buff1Length];
Buffer.BlockCopy(buff, 1, buff1, 0, buff1Length);
byte buff2Length = buff[buff1Length + 1];
buff2 = new byte[buff2Length];
Buffer.BlockCopy(buff, buff1Length + 2, buff2, 0, buff2Length);
return true;
}
catch
{
buff1 = buff2 = null;
}
return false;
}
}
// Validating a license...
CustomCryptoLicense lic = new CustomCryptoLicense();
lic.ValidationKey = "<<validation key for your project>>";
lic.LicenseCode = "<<License code with custom machine code embedded>>";
// Validate license
MessageBox.Show(lic.Status.ToString());
|
[VB.Net]
Code: | Public Class CustomCryptoLicense
Inherits CryptoLicense
' Override to provide custom machine code
' This example uses a combo of the CPU-ID and motherboard serial as the machine code
' The machine is considered matched if either of the two match
Public Overrides Function GetLocalMachineCode() As Byte()
Dim ret As Byte() = Nothing
Try
ret = CombineBuffersWithLength(GetCPUId(), GetMBSerial())
Catch ex As Exception
End Try
' Fall back to base implementation if failed
If ret Is Nothing = True Or ret.Length = 2 Then
ret = MyBase.GetLocalMachineCode()
End If
Return ret
End Function
Public Overrides Function IsMachineCodeValid() As Boolean
Try
Dim embeddedMachineCode As Byte() = Me.MachineCode
Dim localMachineCode As Byte() = Me.GetLocalMachineCode()
Dim cpuid1, cpuid2, mbserial1, mbserial2 As Byte()
cpuid1 = Nothing
cpuid2 = Nothing
mbserial1 = Nothing
mbserial2 = Nothing
If (SplitBuffer(embeddedMachineCode, cpuid1, mbserial1) And SplitBuffer(localMachineCode, cpuid2, mbserial2)) Then
' Consider valid of either cpu-id or mb-serial matches
If (AreBuffersEqual(cpuid1, cpuid2) Or AreBuffersEqual(mbserial1, mbserial2)) Then
Return True
Else
Return False
End If
End If
Catch ex As Exception
End Try
' Fall back to base implementation if failed
Return MyBase.IsMachineCodeValid()
End Function
' Gets the CPU-ID of the local machine
Protected Shared Function GetCPUId() As Byte()
Dim mgmt As ManagementClass = New ManagementClass("Win32_Processor")
Dim objCol As ManagementObjectCollection = mgmt.GetInstances()
Dim obj As ManagementObject
For Each obj In objCol
' Only use CPU-ID from the first CPU
Dim cpuInfo As String = obj.Properties("ProcessorId").Value.ToString()
If (cpuInfo Is Nothing = False And cpuInfo.Length > 0) Then
Dim ret As Byte() = Encoding.UTF8.GetBytes(cpuInfo)
Return ret
End If
Next
Return New Byte(0) {}
End Function
Protected Shared Function GetMBSerial() As Byte()
Try
Dim mgmt As ManagementClass = New ManagementClass("Win32_BaseBoard")
Dim objCol As ManagementObjectCollection = mgmt.GetInstances()
Dim obj As ManagementObject
For Each obj In objCol
' Only use CPU-ID from the first CPU
Dim mbserial As String = obj.Properties("SerialNumber").Value.ToString()
If (mbserial Is Nothing = False And mbserial.Length > 0) Then
Dim ret As Byte() = Encoding.UTF8.GetBytes(mbserial)
Return ret
End If
Next
Catch ex As Exception
End Try
Return New Byte(0) {}
End Function
Shared Function CombineBuffersWithLength(ByVal buff1 As Byte(), ByVal buff2 As Byte()) As Byte()
' Returned format is:
' buff1length-....buff1....-buff2length-...buff2....
Dim ret As Byte() = New Byte(buff1.Length + buff2.Length + 2) {}
ret(0) = CType(buff1.Length, Byte)
buff1.CopyTo(ret, 1)
ret(buff1.Length + 1) = CType(buff2.Length, Byte)
buff2.CopyTo(ret, buff1.Length + 2)
Return ret
End Function
Shared Function AreBuffersEqual(ByVal buff1 As Byte(), ByVal buff2 As Byte()) As Boolean
Try
If (buff1.Length <> buff2.Length) Then
Return False
End If
Dim i As Integer
For i = 0 To buff1.Length - 1
If (buff1(i) <> buff2(i)) Then
Return False
End If
Next i
Return True
Catch ex As Exception
End Try
Return False
End Function
' Gets machine code components
Shared Function SplitBuffer(ByVal buff As Byte(), ByRef buff1 As Byte(), ByRef buff2 As Byte()) As Boolean
buff1 = Nothing
buff2 = Nothing
Try
Dim buff1Length As Byte = buff(0)
buff1 = New Byte(buff1Length) {}
Buffer.BlockCopy(buff, 1, buff1, 0, buff1Length)
Dim buff2Length As Byte = buff(buff1Length + 1)
buff2 = New Byte(buff2Length) {}
Buffer.BlockCopy(buff, buff1Length + 2, buff2, 0, buff2Length)
Return True
Catch
buff1 = Nothing
buff2 = Nothing
End Try
Return False
End Function
End Class
' Validating a license...
Dim lic As CustomCryptoLicense = New CustomCryptoLicense()
lic.ValidationKey = "<<validation key for your project>>"
lic.LicenseCode = "<<License code with custom machine code embedded>>"
' Validate license
MessageBox.Show(lic.Status.ToString())
|
|
|