using System;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using DeviceId;
using DeviceId.Components;
using Kavita.Common.EnvironmentInfo;
namespace Kavita.Common;
public static class HashUtil
{
private static string CalculateCrc(string input)
{
var mCrc = 0xffffffff;
var bytes = Encoding.UTF8.GetBytes(input);
foreach (var myByte in bytes)
{
mCrc ^= (uint)myByte << 24;
for (var i = 0; i < 8; i++)
{
if ((Convert.ToUInt32(mCrc) & 0x80000000) == 0x80000000)
{
mCrc = (mCrc << 1) ^ 0x04C11DB7;
}
else
{
mCrc <<= 1;
}
}
}
return $"{mCrc:x8}";
}
///
/// Calculates a unique, Anonymous Token that will represent this unique Kavita installation.
///
///
public static string AnonymousToken()
{
var seed = $"{Environment.ProcessorCount}_{Environment.OSVersion.Platform}_{Configuration.JwtToken}_{Environment.UserName}";
return CalculateCrc(seed);
}
public static string ServerToken()
{
var seed = new DeviceIdBuilder()
.AddMacAddress()
.AddUserName()
.AddComponent("ProcessorCount", new DeviceIdComponent($"{Environment.ProcessorCount}"))
.AddComponent("OSPlatform", new DeviceIdComponent($"{Environment.OSVersion.Platform}"))
.OnWindows(windows => windows
.AddProcessorId())
.OnLinux(linux =>
{
var osInfo = RunAndCapture("uname", "-a");
if (Regex.IsMatch(osInfo, @"\bUnraid\b"))
{
var cpuModel = RunAndCapture("lscpu", string.Empty);
var match = Regex.Match(cpuModel, @"Model name:\s+(.+)");
linux.AddComponent("CPUModel", new DeviceIdComponent($"{match.Groups[1].Value.Trim()}"));
return;
}
linux.AddMotherboardSerialNumber();
})
.OnMac(mac => mac.AddSystemDriveSerialNumber())
.ToString();
return CalculateCrc(seed);
}
///
/// Generates a unique API key to this server instance
///
///
public static string ApiKey()
{
var id = Guid.NewGuid();
if (id.Equals(Guid.Empty))
{
id = Guid.NewGuid();
}
return id.ToString();
}
private static string RunAndCapture(string filename, string args)
{
var p = new Process
{
StartInfo =
{
FileName = filename,
Arguments = args,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true
}
};
p.Start();
// To avoid deadlocks, always read the output stream first and then wait.
var output = p.StandardOutput.ReadToEnd();
p.WaitForExit(1000);
return output;
}
}