using steam_token.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Util;
namespace steam_token.Util
{
public class SteamTwoFactorToken
{
private static byte[] s_rgchSteamguardCodeChars = { 50, 51, 52, 53, 54, 55, 56, 57, 66, 67, 68, 70, 71, 72, 74, 75, 77, 78, 80, 81, 82, 84, 86, 87, 88, 89 };
private byte[] mSecret;
public SteamTwoFactorToken(string sharedSecret)
{
try
{
if (!string.IsNullOrEmpty(sharedSecret))
{
this.mSecret = Convert.FromBase64String(sharedSecret);
}
else
{
MessageBox.Show("请配置shared_secret值");
}
}
catch (Exception)
{
ConfigUtil.Init(new Config());
MessageBox.Show("shared_secret值不符合要求, 请重新设置");
}
ConfigUtil.INIT_SUCCESS = true;
}
public static bool Verify(string sharedSecret)
{
try
{
byte[] base64 = Convert.FromBase64String(sharedSecret);
Console.WriteLine("source: " + sharedSecret + ", base64 = " + base64);
return true;
}
catch (Exception)
{
MessageBox.Show("shared_secret值校验失败, 请重新设置");
return false;
}
}
public static string GenerateSteamGuardCode(string sharedSecret)
{
return new SteamTwoFactorToken(sharedSecret).GenerateSteamGuardCode();
}
public string GenerateSteamGuardCode()
{
return GenerateSteamGuardCodeForTime(CurrentTime());
}
private string GenerateSteamGuardCodeForTime(long calcTime)
{
if (this.mSecret == null)
{
return "";
}
byte[] bArr = new byte[8];
long j2 = calcTime / 30;
int i = 8;
while (true)
{
int i2 = i - 1;
if (i <= 0)
{
break;
}
bArr[i2] = (byte)((int)j2);
j2 = RightMove(j2, 8);
i = i2;
}
HMACSHA1 hmacsha1 = new HMACSHA1();
hmacsha1.Key = (this.mSecret);
byte[] doFinal = hmacsha1.ComputeHash(bArr);
int i3 = doFinal[19] & 15;
int i4 = (doFinal[i3 + 3] & 255) | ((doFinal[i3 + 2] & 255) << 8) | ((doFinal[i3] & 127) << 24) | ((doFinal[i3 + 1] & 255) << 16);
byte[] bArr2 = new byte[5];
for (int i5 = 0; i5 < 5; i5++)
{
byte[] bArr3 = s_rgchSteamguardCodeChars;
bArr2[i5] = bArr3[i4 % bArr3.Length];
i4 /= bArr3.Length;
}
return System.Text.Encoding.UTF8.GetString(bArr2);
}
public long CurrentTime()
{
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000;
}
///
/// 无符号右移, 相当于java里的 value>>>pos
///
///
///
///
public long RightMove(long value, int pos)
{
//移动 0 位时直接返回原值
if (pos != 0)
{
// int.MaxValue = 0x7FFFFFFF 整数最大值
int mask = int.MaxValue;
//无符号整数最高位不表示正负但操作数还是有符号的,有符号数右移1位,正数时高位补0,负数时高位补1
value = value >> 1;
//和整数最大值进行逻辑与运算,运算后的结果为忽略表示正负值的最高位
value = value & mask;
//逻辑运算后的值无符号,对无符号的值直接做右移运算,计算剩下的位
value = value >> pos - 1;
}
return value;
}
}
}