using Microsoft.Win32; using System; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; namespace AnotherReplayReader { internal static class Auth { public static string? Id { get; } static Auth() { Id = null; string? windowsID; try { using var view64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); using var winNt = view64?.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion", false); windowsID = winNt?.GetValue("ProductId") as string; } catch { return; } string? randomKey; try { var folderPath = Cache.CacheDirectory; if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } var keyPath = Path.Combine(folderPath, "id"); if (!File.Exists(keyPath)) { File.WriteAllText(keyPath, Guid.NewGuid().ToString()); } randomKey = File.ReadAllText(keyPath); } catch { return; } if (string.IsNullOrWhiteSpace(windowsID) || string.IsNullOrWhiteSpace(randomKey)) { return; } using var sha = SHA256.Create(); var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(windowsID + randomKey)); Id = string.Concat(hash.Skip(3).Take(10).Select(x => $"{x:X2}")); } public static string GetKey() { if (Id == null) { return string.Empty; } var text = $"{Id}{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}"; var bytes = Encoding.UTF8.GetBytes(text); var pre = Encoding.UTF8.GetBytes("playertable!"); var salt = new byte[9]; using (var rng = new RNGCryptoServiceProvider()) { rng.GetNonZeroBytes(salt); } for (var i = 0; i < bytes.Length; ++i) { bytes[i] = (byte)(bytes[i] ^ salt[i % salt.Length]); } return Convert.ToBase64String(salt.Concat(bytes).Select((x, i) => (byte)(x ^ pre[i % pre.Length])).ToArray()); } public static byte[]? IdAsKey() { if (string.IsNullOrEmpty(Id)) { return null; } var bytes = Encoding.UTF8.GetBytes(Id); var destination = Enumerable.Repeat(0xEA, 24).ToArray(); Array.Copy(bytes, destination, Math.Min(bytes.Length, destination.Length)); return destination; } } }