using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Management; using System.Security; using System.Security.Cryptography; using System.Text; namespace ArchestrAServices.Common; public static class FingerprintedDataProtector { private const string PrefixV1 = "____NCHENC___"; private static readonly byte[] AdditionalEntropy = Value; private static readonly UTF8Encoding Encoding = new UTF8Encoding(); private static byte[] Value => GetHash(string.Format(CultureInfo.InvariantCulture, "{0}, {1}", new object[2] { CpuId(), BiosId() }), string.Format(CultureInfo.InvariantCulture, "{0}, {1}", new object[2] { BaseId(), DiskId() })); public static string Protect(string data) { return Convert.ToBase64String(Protect(Encoding.GetBytes(AttachPrefix(data)))); } public static byte[] Protect(byte[] data) { return ProtectedData.Protect(data, AdditionalEntropy, DataProtectionScope.LocalMachine); } public static string Unprotect(string encoded) { return DetachPrefix(Encoding.GetString(Unprotect(Convert.FromBase64String(encoded)))); } public static byte[] Unprotect(byte[] encoded) { return ProtectedData.Unprotect(encoded, AdditionalEntropy, DataProtectionScope.LocalMachine); } private static string AttachPrefix(string toEncode) { return "____NCHENC___" + toEncode; } private static string BaseId() { Dictionary dictionary = Identifier("Win32_BaseBoard", "Model", "Manufacturer", "Name", "SerialNumber"); return string.Format(CultureInfo.InvariantCulture, "{0}-{1}-{2}-{3}", dictionary["Model"], dictionary["Manufacturer"], dictionary["Name"], dictionary["SerialNumber"]); } private static string BiosId() { Dictionary dictionary = Identifier("Win32_BIOS", "Manufacturer", "IdentificationCode"); return string.Format(CultureInfo.InvariantCulture, "{0}-{1}", new object[2] { dictionary["Manufacturer"], dictionary["IdentificationCode"] }); } private static string CpuId() { Dictionary dictionary = Identifier("Win32_Processor", "UniqueId", "ProcessorId", "Name", "Manufacturer", "MaxClockSpeed"); return string.Format(CultureInfo.InvariantCulture, "{0}-{1}-{2}-{3}-{4}", dictionary["UniqueId"], dictionary["ProcessorId"], dictionary["Name"], dictionary["Manufacturer"], dictionary["MaxClockSpeed"]); } private static string DetachPrefix(string decoded) { if (decoded.Length > "____NCHENC___".Length && decoded.StartsWith("____NCHENC___", StringComparison.Ordinal)) { return decoded.Substring("____NCHENC___".Length); } throw new SecurityException("Invalid encoded string."); } private static string DiskId() { Dictionary dictionary = Identifier("Win32_DiskDrive", "Model", "Manufacturer", "Signature", "TotalHeads"); return string.Format(CultureInfo.InvariantCulture, "{0}-{1}-{2}-{3}", dictionary["Model"], dictionary["Manufacturer"], dictionary["Signature"], dictionary["TotalHeads"]); } private static byte[] GetHash(string partOne, string partTwo) { byte[] bytes = new UTF8Encoding().GetBytes(partTwo); using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(partOne, bytes); return rfc2898DeriveBytes.GetBytes(16); } private static Dictionary Identifier(string wmiClass, params string[] wmiProperties) { Dictionary dictionary = new Dictionary(wmiProperties.Length); string[] array = wmiProperties; foreach (string key in array) { dictionary[key] = string.Empty; } using ManagementClass managementClass = new ManagementClass(wmiClass); foreach (ManagementObject item in managementClass.GetInstances().Cast()) { array = wmiProperties; foreach (string text in array) { try { dictionary[text] = item[text].ToString(); } catch (Exception) { dictionary[text] = string.Empty; } } } return dictionary; } }