mirror of
https://github.com/Obfuscator-Collections/VMProtect.git
synced 2026-09-01 05:24:42 +03:00
first commit
Version 3.x.x
This commit is contained in:
@@ -0,0 +1,664 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Cache;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Numerics;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace VMProtect
|
||||
{
|
||||
public class LicensingManager
|
||||
{
|
||||
public class BaseRequest
|
||||
{
|
||||
protected bool BuildUrl(byte[] licenseData)
|
||||
{
|
||||
var urlSize = BitConverter.ToInt32(licenseData, (int)Fields.ActivationUrlSize * sizeof(uint));
|
||||
if (urlSize == 0)
|
||||
return false;
|
||||
|
||||
var urlOffset = BitConverter.ToInt32(licenseData, (int)Fields.ActivationUrlOffset * sizeof(uint));
|
||||
Url = Encoding.UTF8.GetString(licenseData, urlOffset, urlSize);
|
||||
if (Url[Url.Length - 1] != '/')
|
||||
Url += '/';
|
||||
return true;
|
||||
}
|
||||
protected void EncodeUrl()
|
||||
{
|
||||
Url = Convert.ToBase64String(Encoding.UTF8.GetBytes(Url));
|
||||
}
|
||||
protected void AppendUrlParam(string param, string value)
|
||||
{
|
||||
AppendUrl(param, false);
|
||||
AppendUrl(value, true);
|
||||
}
|
||||
private void AppendUrl(string str, bool escape)
|
||||
{
|
||||
if (escape)
|
||||
{
|
||||
var sb = new StringBuilder(Url);
|
||||
foreach (var c in str)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '+':
|
||||
sb.Append("%2B");
|
||||
break;
|
||||
case '/':
|
||||
sb.Append("%2F");
|
||||
break;
|
||||
case '=':
|
||||
sb.Append("%3D");
|
||||
break;
|
||||
default:
|
||||
sb.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Url = sb.ToString();
|
||||
} else
|
||||
{
|
||||
Url += str;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Send()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var wc = new WebClient())
|
||||
{
|
||||
ServicePointManager.ServerCertificateValidationCallback +=
|
||||
(sender, certificate, chain, sslPolicyErrors) => true;
|
||||
wc.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
|
||||
wc.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
|
||||
Response = wc.DownloadString(Url);
|
||||
try
|
||||
{
|
||||
var strDt = wc.ResponseHeaders.Get("Date");
|
||||
var dt = DateTime.ParseExact(strDt, "ddd, dd MMM yyyy HH:mm:ss 'GMT'",
|
||||
CultureInfo.InvariantCulture.DateTimeFormat, DateTimeStyles.AssumeUniversal);
|
||||
GlobalData.SetServerDate((uint)((dt.Year << 16) + (dt.Month << 8) + dt.Day));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//не смогли вытащить дату из заголовков - прощаем?
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public string Url { get; private set; }
|
||||
public string Response { get; private set; }
|
||||
}
|
||||
|
||||
public class ActivationRequest : BaseRequest
|
||||
{
|
||||
public ActivationStatus Process(byte[] licenseData, string code, bool offline)
|
||||
{
|
||||
if (!VerifyCode(code))
|
||||
return ActivationStatus.BadCode;
|
||||
|
||||
if (!BuildUrl(licenseData, code, offline))
|
||||
return ActivationStatus.NotAvailable;
|
||||
|
||||
if (offline)
|
||||
return ActivationStatus.Ok;
|
||||
|
||||
if (!Send())
|
||||
return ActivationStatus.NoConnection;
|
||||
|
||||
var res = Response;
|
||||
if (string.IsNullOrEmpty(res))
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
// possible answers: OK, BAD, BANNED, USED, EXPIRED
|
||||
// if OK - see the Serial number below
|
||||
|
||||
if (res == "BAD")
|
||||
return ActivationStatus.BadCode;
|
||||
|
||||
if (res == "BANNED")
|
||||
return ActivationStatus.Banned;
|
||||
|
||||
if (res == "USED")
|
||||
return ActivationStatus.AlreadyUsed;
|
||||
|
||||
if (res == "EXPIRED")
|
||||
return ActivationStatus.Expired;
|
||||
|
||||
var crPos = res.IndexOf('\n');
|
||||
if (crPos != 2)
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
if (res[0] != 'O' || res[1] != 'K')
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
if (res.Length - 3 < 64)
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
Serial = res.Substring(3);
|
||||
return ActivationStatus.Ok;
|
||||
}
|
||||
public string Serial
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
private bool VerifyCode(string code)
|
||||
{
|
||||
if (string.IsNullOrEmpty(code) || code.Length > 32)
|
||||
return false;
|
||||
return code.ToLower().TrimEnd("0123456789abcdefghijklmnopqrstuvwxyz-".ToCharArray()).Length == 0;
|
||||
}
|
||||
private bool BuildUrl(byte[] licenseData, string code, bool offline)
|
||||
{
|
||||
if (!offline) {
|
||||
if (!base.BuildUrl(licenseData))
|
||||
return false;
|
||||
}
|
||||
|
||||
// hwid -> base64
|
||||
var hwid = Convert.ToBase64String(Core.Instance.HWID.GetBytes());
|
||||
|
||||
// hash -> base64
|
||||
var modSize = BitConverter.ToInt32(licenseData, (int)Fields.ModulusSize * sizeof(uint));
|
||||
var modOffset = BitConverter.ToInt32(licenseData, (int)Fields.ModulusOffset * sizeof(uint));
|
||||
using (var sha = new SHA1Managed())
|
||||
{
|
||||
var modulus = sha.ComputeHash(licenseData, modOffset, modSize);
|
||||
var hash = Convert.ToBase64String(modulus, 0, 20);
|
||||
|
||||
// build Url
|
||||
AppendUrlParam(offline ? "type=activation&code=" : "activation.php?code=", code);
|
||||
AppendUrlParam("&hwid=", hwid);
|
||||
AppendUrlParam("&hash=", hash);
|
||||
}
|
||||
|
||||
if (offline)
|
||||
EncodeUrl();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class DeactivationRequest : BaseRequest
|
||||
{
|
||||
public ActivationStatus Process(byte[] licenseData, string serial, bool offline)
|
||||
{
|
||||
if (!VerifySerial(serial))
|
||||
return ActivationStatus.BadCode;
|
||||
|
||||
if (!BuildUrl(licenseData, serial, offline))
|
||||
return ActivationStatus.NotAvailable;
|
||||
|
||||
if (offline)
|
||||
return ActivationStatus.Ok;
|
||||
|
||||
if (!Send())
|
||||
return ActivationStatus.NoConnection;
|
||||
|
||||
var res = Response;
|
||||
if (string.IsNullOrEmpty(res))
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
if (res == "OK")
|
||||
return ActivationStatus.Ok;
|
||||
|
||||
if (res == "ERROR")
|
||||
return ActivationStatus.Corrupted;
|
||||
|
||||
if (res == "UNKNOWN")
|
||||
return ActivationStatus.SerialUnknown;
|
||||
|
||||
return ActivationStatus.BadReply;
|
||||
}
|
||||
|
||||
private bool VerifySerial(string serial)
|
||||
{
|
||||
return !string.IsNullOrEmpty(serial);
|
||||
}
|
||||
|
||||
private bool BuildUrl(byte[] licenseData, string serial, bool offline)
|
||||
{
|
||||
if (!offline) {
|
||||
if (!base.BuildUrl(licenseData))
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var serialBytes = Convert.FromBase64String(serial);
|
||||
using (var sha = new SHA1Managed())
|
||||
{
|
||||
var serialHash = sha.ComputeHash(serialBytes);
|
||||
var hash = Convert.ToBase64String(serialHash, 0, 20);
|
||||
|
||||
AppendUrlParam(offline ? "type=deactivation&hash=" : "deactivation.php?hash=", hash);
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offline)
|
||||
EncodeUrl();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public LicensingManager(long instance)
|
||||
{
|
||||
_sessionKey = 0 - GlobalData.SessionKey();
|
||||
_licenseData = new byte[(uint)Faces.LICENSE_INFO_SIZE];
|
||||
Marshal.Copy(new IntPtr(instance + (uint)Faces.LICENSE_INFO), _licenseData, 0, _licenseData.Length);
|
||||
_startTickCount = Environment.TickCount;
|
||||
}
|
||||
public LicensingManager(byte [] licenseData)
|
||||
{
|
||||
_licenseData = licenseData;
|
||||
}
|
||||
public SerialState GetSerialNumberState()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return (_state & (SerialState.Corrupted | SerialState.Invalid | SerialState.BadHwid | SerialState.Blacklisted)) != 0 ? _state : ParseSerial(null);
|
||||
}
|
||||
}
|
||||
public ActivationStatus ActivateLicense(string code, out string serial)
|
||||
{
|
||||
serial = string.Empty;
|
||||
if (!CheckLicenseDataCRC())
|
||||
return ActivationStatus.Corrupted;
|
||||
|
||||
var request = new ActivationRequest();
|
||||
var res = request.Process(_licenseData, code, false);
|
||||
if (res == ActivationStatus.Ok)
|
||||
{
|
||||
serial = request.Serial;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public ActivationStatus DeactivateLicense(string serial)
|
||||
{
|
||||
return CheckLicenseDataCRC() ?
|
||||
new DeactivationRequest().Process(_licenseData, serial, false) :
|
||||
ActivationStatus.Corrupted;
|
||||
}
|
||||
|
||||
public ActivationStatus GetOfflineActivationString(string code, out string buf)
|
||||
{
|
||||
buf = string.Empty;
|
||||
if (!CheckLicenseDataCRC())
|
||||
return ActivationStatus.Corrupted;
|
||||
|
||||
var request = new ActivationRequest();
|
||||
var res = request.Process(_licenseData, code, true);
|
||||
if (res == ActivationStatus.Ok)
|
||||
{
|
||||
buf = request.Url;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public ActivationStatus GetOfflineDeactivationString(string serial, out string buf)
|
||||
{
|
||||
buf = string.Empty;
|
||||
if (!CheckLicenseDataCRC())
|
||||
return ActivationStatus.Corrupted;
|
||||
|
||||
var request = new DeactivationRequest();
|
||||
var res = request.Process(_licenseData, serial, true);
|
||||
if (res == ActivationStatus.Ok)
|
||||
{
|
||||
buf = request.Url;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static BigInteger B2Bi(byte[] b) //reverse & make positive
|
||||
{
|
||||
Array.Reverse(b);
|
||||
var b2 = new byte[b.Length + 1];
|
||||
Array.Copy(b, b2, b.Length);
|
||||
return new BigInteger(b2);
|
||||
}
|
||||
|
||||
public SerialState SetSerialNumber(string serial)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
SaveState(SerialState.Invalid);
|
||||
|
||||
if (string.IsNullOrEmpty(serial))
|
||||
return SerialState.Invalid; // the key is empty
|
||||
|
||||
// decode serial number from base64
|
||||
byte[] binarySerial;
|
||||
try
|
||||
{
|
||||
binarySerial = Convert.FromBase64String(serial);
|
||||
if (binarySerial.Length < 16)
|
||||
return SerialState.Invalid;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return SerialState.Invalid;
|
||||
}
|
||||
|
||||
// check license data integrity
|
||||
if (!CheckLicenseDataCRC()) {
|
||||
return SaveState(SerialState.Corrupted);
|
||||
}
|
||||
|
||||
// check serial by black list
|
||||
var blackListSize = BitConverter.ToInt32(_licenseData, (int)Fields.BlacklistSize * sizeof(uint));
|
||||
if (blackListSize != 0) {
|
||||
var blackListOffset = BitConverter.ToInt32(_licenseData, (int)Fields.BlacklistOffset * sizeof(uint));
|
||||
|
||||
using (var hash = new SHA1Managed())
|
||||
{
|
||||
var p = hash.ComputeHash(binarySerial);
|
||||
int min = 0;
|
||||
int max = blackListSize / 20 - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int i = (min + max) / 2;
|
||||
var blocked = true;
|
||||
for (var j = 0; j < 20 / sizeof(uint); j++) {
|
||||
var dw = BitConverter.ToUInt32(_licenseData, blackListOffset + i * 20 + j * sizeof(uint));
|
||||
var v = BitConverter.ToUInt32(p, j * sizeof(uint));
|
||||
if (dw == v)
|
||||
continue;
|
||||
|
||||
if (BitRotate.Swap(dw) > BitRotate.Swap(v))
|
||||
{
|
||||
max = i - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = i + 1;
|
||||
}
|
||||
blocked = false;
|
||||
break;
|
||||
}
|
||||
if (blocked) {
|
||||
return SaveState(SerialState.Blacklisted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// decode serial number
|
||||
var ebytes = new byte[BitConverter.ToInt32(_licenseData, (int)Fields.PublicExpSize * sizeof(uint))];
|
||||
Array.Copy(_licenseData, BitConverter.ToInt32(_licenseData, (int)Fields.PublicExpOffset * sizeof(uint)), ebytes, 0, ebytes.Length);
|
||||
var e = B2Bi(ebytes);
|
||||
var nbytes = new byte[BitConverter.ToInt32(_licenseData, (int)Fields.ModulusSize * sizeof(uint))];
|
||||
Array.Copy(_licenseData, BitConverter.ToInt32(_licenseData, (int)Fields.ModulusOffset * sizeof(uint)), nbytes, 0, nbytes.Length);
|
||||
var n = B2Bi(nbytes);
|
||||
var x = B2Bi(binarySerial);
|
||||
|
||||
if (n < x) {
|
||||
// data is too long to crypt
|
||||
return SerialState.Invalid;
|
||||
}
|
||||
|
||||
_serial = BigInteger.ModPow(x, e, n).ToByteArray();
|
||||
Array.Reverse(_serial);
|
||||
|
||||
if (_serial[0] != 0 || _serial[1] != 2)
|
||||
return SerialState.Invalid;
|
||||
|
||||
int pos;
|
||||
for (pos = 2; pos < _serial.Length; pos++) {
|
||||
if (_serial[pos] == 0) {
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos == _serial.Length)
|
||||
return SerialState.Invalid;
|
||||
|
||||
_start = pos;
|
||||
return ParseSerial(null);
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetSerialNumberData(SerialNumberData data)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_state == SerialState.Corrupted)
|
||||
return false;
|
||||
|
||||
data.State = (_state & (SerialState.Invalid | SerialState.Blacklisted | SerialState.BadHwid)) != 0 ? _state : ParseSerial(data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public uint DecryptBuffer(uint p3, uint p2, uint p1, uint p0)
|
||||
{
|
||||
uint key0 = (uint)_productCode;
|
||||
uint key1 = (uint)(_productCode >> 32) + _sessionKey;
|
||||
|
||||
p0 = BitRotate.Left((p0 + _sessionKey) ^ key0, 7) + key1;
|
||||
p1 = BitRotate.Left((p1 + _sessionKey) ^ key0, 11) + key1;
|
||||
p2 = BitRotate.Left((p2 + _sessionKey) ^ key0, 17) + key1;
|
||||
p3 = BitRotate.Left((p3 + _sessionKey) ^ key0, 23) + key1;
|
||||
|
||||
if (p0 + p1 + p2 + p3 != _sessionKey * 4)
|
||||
{
|
||||
Core.ShowMessage("This code requires valid serial number to run.\nProgram will be terminated.");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
return p3;
|
||||
}
|
||||
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
private enum ChunkType
|
||||
{
|
||||
Version = 0x01, // 1 byte of data - version
|
||||
UserName = 0x02, // 1 + N bytes - length + N bytes of customer's name (without enging \0).
|
||||
Email = 0x03, // 1 + N bytes - length + N bytes of customer's email (without ending \0).
|
||||
HWID = 0x04, // 1 + N bytes - length + N bytes of hardware id (N % 4 == 0)
|
||||
ExpDate = 0x05, // 4 bytes - (year << 16) + (month << 8) + (day)
|
||||
RunningTimeLimit = 0x06, // 1 byte - number of minutes
|
||||
ProductCode = 0x07, // 8 bytes - used for decrypting some parts of exe-file
|
||||
UserData = 0x08, // 1 + N bytes - length + N bytes of user data
|
||||
MaxBuild = 0x09, // 4 bytes - (year << 16) + (month << 8) + (day)
|
||||
End = 0xFF // 4 bytes - checksum: the first four bytes of sha-1 hash from the data before that chunk
|
||||
}
|
||||
|
||||
private SerialState SaveState(SerialState state)
|
||||
{
|
||||
_state = state;
|
||||
if ((_state & (SerialState.Invalid | SerialState.BadHwid)) != 0)
|
||||
{
|
||||
_serial = null;
|
||||
_productCode = 0;
|
||||
}
|
||||
return _state;
|
||||
}
|
||||
private SerialState ParseSerial(SerialNumberData data)
|
||||
{
|
||||
if (_serial == null)
|
||||
return SerialState.Invalid;
|
||||
|
||||
var newState = _state & (SerialState.MaxBuildExpired | SerialState.DateExpired | SerialState.RunningTimeOver);
|
||||
var pos = _start;
|
||||
while (pos < _serial.Length) {
|
||||
var b = _serial[pos++];
|
||||
byte s;
|
||||
switch (b) {
|
||||
case (byte)ChunkType.Version:
|
||||
if (_serial[pos] != 1)
|
||||
return SaveState(SerialState.Invalid);
|
||||
pos += 1;
|
||||
break;
|
||||
case (byte)ChunkType.ExpDate:
|
||||
var expDate = BitConverter.ToUInt32(_serial, pos);
|
||||
if ((newState & SerialState.DateExpired) == 0) {
|
||||
if (BitConverter.ToUInt32(_licenseData, (int)Fields.BuildDate * sizeof(uint)) > expDate || GetCurrentDate() > expDate)
|
||||
newState |= SerialState.DateExpired;
|
||||
}
|
||||
if (data != null) {
|
||||
data.Expires = new DateTime((int)(expDate >> 16), (byte)(expDate >> 8), (byte)expDate);
|
||||
}
|
||||
pos += 4;
|
||||
break;
|
||||
case (byte)ChunkType.RunningTimeLimit:
|
||||
s = _serial[pos];
|
||||
if ((newState & SerialState.RunningTimeOver) == 0) {
|
||||
var curTime = (Environment.TickCount - _startTickCount) / 1000 / 60;
|
||||
if (curTime > s)
|
||||
newState |= SerialState.RunningTimeOver;
|
||||
}
|
||||
if (data != null)
|
||||
data.RunningTime = s;
|
||||
pos += 1;
|
||||
break;
|
||||
case (byte)ChunkType.ProductCode:
|
||||
if ((_state & SerialState.Invalid) != 0)
|
||||
_productCode = BitConverter.ToInt64(_serial, pos);
|
||||
pos += 8;
|
||||
break;
|
||||
case (byte)ChunkType.MaxBuild:
|
||||
var maxBuildDate = BitConverter.ToUInt32(_serial, pos);
|
||||
if ((newState & SerialState.MaxBuildExpired) == 0) {
|
||||
if (BitConverter.ToUInt32(_licenseData, (int)Fields.BuildDate * sizeof(uint)) > maxBuildDate)
|
||||
newState |= SerialState.MaxBuildExpired;
|
||||
}
|
||||
if (data != null)
|
||||
{
|
||||
data.MaxBuild = new DateTime((int)(maxBuildDate >> 16), (byte)(maxBuildDate >> 8), (byte)maxBuildDate);
|
||||
}
|
||||
pos += 4;
|
||||
break;
|
||||
case (byte)ChunkType.UserName:
|
||||
s = _serial[pos++];
|
||||
if (data != null)
|
||||
data.UserName = Encoding.UTF8.GetString(_serial, pos, s);
|
||||
pos += s;
|
||||
break;
|
||||
case (byte)ChunkType.Email:
|
||||
s = _serial[pos++];
|
||||
if (data != null)
|
||||
data.EMail = Encoding.UTF8.GetString(_serial, pos, s);
|
||||
pos += s;
|
||||
break;
|
||||
case (byte)ChunkType.HWID:
|
||||
s = _serial[pos++];
|
||||
if ((_state & SerialState.Invalid) != 0)
|
||||
{
|
||||
var shwid = new byte[s];
|
||||
Array.Copy(_serial, pos, shwid, 0, s);
|
||||
if (!Core.Instance.HWID.IsCorrect(shwid))
|
||||
return SaveState(SerialState.BadHwid);
|
||||
}
|
||||
pos += s;
|
||||
break;
|
||||
case (byte)ChunkType.UserData:
|
||||
s = _serial[pos++];
|
||||
if (data != null) {
|
||||
data.UserData = new byte[s];
|
||||
for (var i = 0; i < s; i++) {
|
||||
data.UserData[i] = _serial[pos + i];
|
||||
}
|
||||
}
|
||||
pos += s;
|
||||
break;
|
||||
case (byte)ChunkType.End:
|
||||
if (pos + 4 > _serial.Length)
|
||||
return SaveState(SerialState.Invalid);
|
||||
|
||||
if ((_state & SerialState.Invalid) != 0) {
|
||||
// calc hash without last chunk
|
||||
using (var hash = new SHA1Managed())
|
||||
{
|
||||
var p = hash.ComputeHash(_serial, _start, pos - _start - 1);
|
||||
|
||||
// check CRC
|
||||
for (var i = 0; i < 4; i++) {
|
||||
if (_serial[pos + i] != p[3 - i])
|
||||
return SaveState(SerialState.Invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SaveState(newState);
|
||||
}
|
||||
}
|
||||
|
||||
// SERIAL_CHUNK_END not found
|
||||
return SaveState(SerialState.Invalid);
|
||||
}
|
||||
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
internal enum Fields
|
||||
{
|
||||
BuildDate,
|
||||
PublicExpOffset,
|
||||
PublicExpSize,
|
||||
ModulusOffset,
|
||||
ModulusSize,
|
||||
BlacklistOffset,
|
||||
BlacklistSize,
|
||||
ActivationUrlOffset,
|
||||
ActivationUrlSize,
|
||||
CRCOffset,
|
||||
Count
|
||||
}
|
||||
private bool CheckLicenseDataCRC()
|
||||
{
|
||||
var crcPos = BitConverter.ToInt32(_licenseData, (int)Fields.CRCOffset * sizeof(uint));
|
||||
var size = crcPos + 16;
|
||||
if (size != _licenseData.Length)
|
||||
return false; // bad key size
|
||||
|
||||
// CRC check
|
||||
using (var hash = new SHA1Managed())
|
||||
{
|
||||
var h = hash.ComputeHash(_licenseData, 0, crcPos);
|
||||
for (var i = crcPos; i < size; i++)
|
||||
{
|
||||
if (_licenseData[i] != h[i - crcPos])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static uint GetCurrentDate()
|
||||
{
|
||||
var dt = DateTime.Now;
|
||||
var curDate = (uint)((dt.Year << 16) + (dt.Month << 8) + dt.Day);
|
||||
var serverDate = GlobalData.ServerDate();
|
||||
return serverDate > curDate ? serverDate : curDate;
|
||||
}
|
||||
|
||||
private readonly byte[] _licenseData;
|
||||
private byte[] _serial;
|
||||
private readonly object _lock = new object();
|
||||
private SerialState _state = SerialState.Invalid;
|
||||
//TODO
|
||||
//ReSharper disable once NotAccessedField.Local
|
||||
private long _productCode;
|
||||
private readonly int _startTickCount;
|
||||
private int _start;
|
||||
private uint _sessionKey;
|
||||
/*
|
||||
CryptoContainer *_serial;
|
||||
*/
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user