using System.Globalization;
using System.Security.Cryptography;
public static void Main()
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
var secretHash = GetInput(">请输入秘密哈希:");
var secretSalt = GetInput(">请输入秘密盐:");
var publicHash = GetInput(">请输入公开哈希:");
var clientSeed = GetInput(">请输入用户种子:");
if (publicHash == HashUtil.GeneratePublishHash(secretHash, secretSalt))
Console.WriteLine("公开哈希有效");
Console.WriteLine("公开哈希无效");
var roundInString = GetInput("请输入回合数:");
if (!int.TryParse(roundInString, out int round))
var rollNumber = HashUtil.ComputeRollNumber(secretHash, clientSeed, round);
Console.WriteLine($"回合数为 {round} 时的Roll点为 {rollNumber}");
private static string GetInput(string prompt)
while (string.IsNullOrWhiteSpace(line)) {
line = Console.ReadLine();
public static class HashUtil
public const long ROLL_SEED_MIN = 0L;
public const long ROLL_SEED_MAX = 1_000_000L;
public static string GeneratePublishHash(string secretHash, string secretSalt)
var bytes = Unhexlify(secretHash + secretSalt);
using var hash = SHA256.Create();
var hashBytes = hash.ComputeHash(bytes);
return HexDigest(hashBytes);
public static int ComputeRollNumber(string secretHash, string clientSeed, int round)
var secret = Unhexlify(secretHash);
var seed = $"{clientSeed}-{round}";
using HMACSHA512 hmac = new HMACSHA512(secret);
var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(seed));
var hash = HexDigest(hashBytes);
var subHash = hash.Substring(0,7);
var number = long.Parse(subHash, NumberStyles.HexNumber);
return (int)(number % ROLL_SEED_MAX + ROLL_SEED_MIN);
private static byte[] Unhexlify(string text)
if ((text.Length % 2) != 0)
throw new ArgumentException("Invalid length: " + text.Length);
if (text.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
text = text.Substring(2);
int arrayLength = text.Length / 2;
byte[] byteArray = new byte[arrayLength];
for (int i = 0; i < arrayLength; i++)
byteArray[i] = byte.Parse(text.Substring(i * 2, 2), NumberStyles.HexNumber);
private static string HexDigest(byte[] bytes) => BitConverter.ToString(bytes).Replace("-", "").ToLower();