public static int GenerateToken(string base32Key) { var keySize = Encoding.UTF8.GetByteCount(base32Key); int bufferSize = (keySize + 7) / 8 * 5; byte[] decoded = new byte[bufferSize]; int hmacResSize = HMAC_RES_SIZE; Span <byte> hmacRes = stackalloc byte[HMAC_RES_SIZE]; long timestamp = Time.GetTimestamp(Time.Now) / 30; Span <byte> challenge = stackalloc byte[8]; for (int i = 7; i >= 0; i--, timestamp >>= 8) { challenge[i] = (byte)timestamp; } Base32Decode(base32Key, decoded); var hmac = new HMACSHA1(decoded); hmac.TryComputeHash(challenge, hmacRes, out hmacResSize); hmac.Dispose(); int offset = hmacRes[19] & 0xF; int truncHash = (hmacRes[offset] << 24) | (hmacRes[offset + 1] << 16) | (hmacRes[offset + 2] << 8) | (hmacRes[offset + 3]); truncHash &= 0x7FFFFFFF; return(truncHash % 1000000); }