Skip to content

Instantly share code, notes, and snippets.

@mooop12

mooop12/totp.cs Secret

Created July 27, 2018 11:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mooop12/1af7f0ffc8f28ea76f27abcba1e6da01 to your computer and use it in GitHub Desktop.
Save mooop12/1af7f0ffc8f28ea76f27abcba1e6da01 to your computer and use it in GitHub Desktop.
PoC program to generate Steam TOTP codes. Mostly copy-paste from https://github.com/winauth/winauth Requires the BouncyCastle nuget package.
using System;
using System.Text;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Parameters;
namespace ConsoleApp1
{
public static class Program
{
private const string Secret = "Put your secret here.";
private const int CodeDigits = 5;
private const int Period = 30;
private const long ServerTimeDiff = 0;
private static readonly byte[] SecretBytes = Convert.FromBase64String(Secret);
private static readonly char[] SteamChars =
{
'2', '3', '4', '5', '6', '7', '8', '9',
'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K',
'M', 'N', 'P', 'Q', 'R', 'T', 'V', 'W',
'X', 'Y'
};
private static long CurrentTime =>
Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds);
private static long ServerTime => CurrentTime - ServerTimeDiff;
private static long CodeInterval => (CurrentTime + ServerTimeDiff) / (Period * 1000);
public static void Main()
{
var hmac = new HMac(new Sha1Digest());
hmac.Init(new KeyParameter(SecretBytes));
var codeIntervalArray = BitConverter.GetBytes(CodeInterval);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(codeIntervalArray);
}
hmac.BlockUpdate(codeIntervalArray, 0, codeIntervalArray.Length);
var mac = new byte[hmac.GetMacSize()];
hmac.DoFinal(mac, 0);
var start = mac[19] & 0x0f;
var bytes = new byte[4];
Array.Copy(mac, start, bytes, 0, 4);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
var fullCode = BitConverter.ToUInt32(bytes, 0) & 0x7fffffff;
var code = new StringBuilder();
for (var i = 0; i < CodeDigits; i++)
{
code.Append(SteamChars[fullCode % SteamChars.Length]);
fullCode /= (uint) SteamChars.Length;
}
Console.WriteLine(code);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment