-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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