using System.Security.Cryptography;
using System.Collections.Generic;
public static void Main()
var epochSecondsIncrement = DateTimeOffset.UtcNow.ToUnixTimeSeconds() / 30;
var list = new List<long>{3, 2, epochSecondsIncrement};
HashAlgorithm md5 = MD5.Create();
var json = JsonSerializer.Serialize(list);
var dataString = $"{(int)list[0]}-{(int)list[1]}-{epochSecondsIncrement}";
var dataArray = Encoding.Unicode.GetBytes(dataString);
byte[] md5out = md5.ComputeHash(dataArray);
UInt32 result = BitConverter.ToUInt32(md5out, 12);
if(result == 0) result++;
var isValid = IsTwoFactorAuthCodeValid((int)list[0], (int)list[1], result);
Console.WriteLine($"Time: {DateTime.Now} code: {result:D6} isValid: {isValid} dataStr: {dataString}");
private static bool IsTwoFactorAuthCodeValid(int clientID, int trackerID, uint code)
var matchingCodes = new List<uint>();
var epochSecondsIncrement = DateTimeOffset.UtcNow.ToUnixTimeSeconds() / 30;
for (int i = -2; i <= 2; i++)
HashAlgorithm md5 = MD5.Create();
var dataString = $"{clientID}-{trackerID}-{epochSecondsIncrement+i}";
var dataArray = Encoding.Unicode.GetBytes(dataString);
byte[] md5out = md5.ComputeHash(dataArray);
var result = BitConverter.ToUInt32(md5out, 12);
if(result == 0) result++;
matchingCodes.Add(result);
Console.WriteLine($"Validator: dataStr: {dataString} i: {i}");
return matchingCodes.Contains(code);