android-otp-extractor icon indicating copy to clipboard operation
android-otp-extractor copied to clipboard

Steam doesn't show letters, just numbers

Open p1r473 opened this issue 4 years ago • 4 comments

Hi, It seems that codes displayed for Steam are showing 5 digits rather than 5 alphanumeric characters. A steam code should have both a mixture of letters and numbers.

I use WinAuth for my emergency backup portable 2FA solution. It does support Steam 2FA and successfully shows alphanumeric instead of all just numbers.

-I would recommend looking at the WinAuth source code to see how the author successfully decodes Steam 2FA to show alphanumeric characters for Steam URIs. -In order to decipher Steam OTP's, WinAuth requires &issuer=Steam in the OTPAuth URI. Please consider appending this to anything exported from Steam (I did it manually... not a big deal. Just would add support for others using WinAuth)

p1r473 avatar May 22 '21 00:05 p1r473

Code for turning the 5 numbers into the proper 5 alphanumeric for steam in these files: https://github.com/winauth/winauth/blob/master/Authenticator/SteamAuthenticator.cs https://github.com/winauth/winauth/blob/master/Authenticator/SteamClient.cs

Or these projects: https://github.com/Jessecar96/SteamDesktopAuthenticator https://github.com/winauth/winauth/

p1r473 avatar May 23 '21 18:05 p1r473

To be honest, the TOTP code generation section of the webpage was just something I added to quickly verify that the codes work. Steam uses a non-standard alphabet for their TOTP codes and it seems easier to outright remove it but if you can find a way to either hack otplib to generate Steam codes or to implement HMAC-SHA1 and the simple HOTP generation code in JavaScript and just generate them without otplib, either would work.

puddly avatar May 23 '21 18:05 puddly

Although I could also just statically generate a bunch of codes per app in Python, since this is a relatively simple change and the codes are glanced at for two periods at most. Maybe I'll give that a try.

puddly avatar May 23 '21 19:05 puddly

I've tried to dig through the above files to find the code for converting the numbers to letters Hopefully this helps.

/// Character set for authenticator code
/// </summary>
private static char[] STEAMCHARS = new char[] {
		'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'};
	HMac hmac = new HMac(new Sha1Digest());
	hmac.Init(new KeyParameter(SecretKey));

	byte[] codeIntervalArray = BitConverter.GetBytes(CodeInterval);
	if (BitConverter.IsLittleEndian)
	{
		Array.Reverse(codeIntervalArray);
	}
	hmac.BlockUpdate(codeIntervalArray, 0, codeIntervalArray.Length);

	byte[] mac = new byte[hmac.GetMacSize()];
	hmac.DoFinal(mac, 0);

	// the last 4 bits of the mac say where the code starts (e.g. if last 4 bit are 1100, we start at byte 12)
	int start = mac[19] & 0x0f;

	// extract those 4 bytes
	byte[] bytes = new byte[4];
	Array.Copy(mac, 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 (var i=0; i<CODE_DIGITS; i++)
	{
		code.Append(STEAMCHARS[fullcode % STEAMCHARS.Length]);
		fullcode /= (uint)STEAMCHARS.Length;
	}

	return code.ToString();
}

p1r473 avatar Jun 01 '21 17:06 p1r473