using System.Globalization; using System.Numerics; using System.Security.Cryptography; using System.Text; namespace AiQ_GUI { public class Lics { // Challenge code salts const string SAFsalt = "F7W?wbD#'[+:v44]tA<:_iK4hQ}+$R{U"; const string Streamsalt = "*;5WPsR5i/$8s1I(M)K5=z3fms{_8x4U"; const string Auditsalt = "4t5e[E06:dXWf:C09Z[h)}V*n>}t0POP"; const string PasswordSalt = "eP@4^4T2@e@^h12oqf!590"; // Generates the license response based on the challenge and type of license public static string GenerateLicCode(string challenge, string Type) { string salt; // Different salts for differnet licenses if (Type == "Store & Forward") salt = SAFsalt; else if (Type == "Streaming") salt = Streamsalt; else if (Type == "Audit") salt = Auditsalt; else return "Unrecognised challenge type: " + Type; if (string.IsNullOrEmpty(challenge) || challenge.Length != 6) // Check challenge format return "Invalid challenge format. Challenge must be 6 characters."; if (string.IsNullOrEmpty(salt) || salt.Length != 32) // Check salt format return "Invalid salt format. Salt must be 32 characters."; // Hash computation using SHA256 algorithm byte[] inputBytes = Encoding.UTF8.GetBytes(challenge + " " + salt); // SHA hash format challenge and salt with space between byte[] hashBytes = SHA256.HashData(inputBytes); StringBuilder sb = new(); foreach (byte b in hashBytes) { sb.Append(b.ToString("x2")); } string digest = sb.ToString(); BigInteger BigInt = BigInteger.Parse("0" + digest, NumberStyles.AllowHexSpecifier); // Leading zero is sign for big int. return BigInt.ToString().Substring(0, 6); } public static string GeneratePassword(string mac, string version, int time) { try { string timeBlock = (time / 86400).ToString(); // 1-day validity string secret = string.Join(" ", mac, version, timeBlock, PasswordSalt); byte[] digest = MD5.HashData(Encoding.UTF8.GetBytes(secret)); return Convert.ToBase64String(digest); } catch (Exception ex) { return "Error: Could not generate password " + ex.Message; } } public static void DisplayDevPassword(Versions Vers, Camera CamOnTest) { CamOnTest.DevPass = FetchDevPassword(Vers); if (CamOnTest.DevPass.Contains("Could not")) { MainForm.Instance.AddToActionsList(CamOnTest.DevPass); // Did not parse, so error. return; } Network.Initialize("developer", CamOnTest.DevPass); // Reinitialise HTTP client with developer password } public static string FetchDevPassword(Versions Vers) { try { return GeneratePassword(Vers.MAC, Vers.version, Vers.timeStamp); } catch (Exception ex) { MainForm.Instance.AddToActionsList("Exception in FetchDevPassword: " + ex.Message); return null; } } } public class Licenses { public bool saf1 { get; set; } public bool saf2 { get; set; } public bool saf3 { get; set; } public bool saf4 { get; set; } public bool audit { get; set; } public bool stream { get; set; } public string raptorKeyID { get; set; } = string.Empty; } public class VaxtorLic { public string protectionKeyId { get; set; } = string.Empty; public string error { get; set; } = string.Empty; } }