private string GenerateTokenForTime(uint time) {
if (time == 0) {
Bot.ArchiLogger.LogNullError(nameof(time));
return null;
}
byte[] sharedSecret = Convert.FromBase64String(SharedSecret);
byte[] timeArray = BitConverter.GetBytes((long) time / CodeInterval);
if (BitConverter.IsLittleEndian) {
Array.Reverse(timeArray);
}
byte[] hash;
using (HMACSHA1 hmac = new HMACSHA1(sharedSecret)) {
hash = hmac.ComputeHash(timeArray);
}
// The last 4 bits of the mac say where the code starts
int start = hash[hash.Length - 1] & 0x0f;
// Extract those 4 bytes
byte[] bytes = new byte[4];
Array.Copy(hash, start, bytes, 0, 4);
if (BitConverter.IsLittleEndian) {
Array.Reverse(bytes);
}
uint fullCode = BitConverter.ToUInt32(bytes, 0) & 0x7fffffff;
// Build the alphanumeric code
StringBuilder code = new StringBuilder();
for (byte i = 0; i < CodeDigits; i++) {
code.Append(CodeCharacters[fullCode % CodeCharacters.Length]);
fullCode /= (uint) CodeCharacters.Length;
}
return code.ToString();
}