一、第一步,申请密钥
2FA 双因素认证,是多因素认证 (MFA) 的一种。登录需要两类不同凭证,除账号密码之外,还需要提供一次性验证码,两者全部校验通过,才可登录账号,避免仅密码泄露就被盗号。
二、第二步,往APP输入密钥
- 此步骤使得APP可以生成正常的登录密码
三、第三步,保存Github给你的密钥、恢复码
- 记住密钥,由Github提供,各大【Authenticator】APP通过TOTP公开协议及密钥生成登录密码,有了密钥+原始账号密码 = 可以成功登录Github
- 记住恢复码,由Github提供,若密钥丢失,用恢复码登录,进入 2FA 设置页,手动编辑更换一套全新 TOTP 密钥
四、C#实现:根据密钥获取登录密码
此代码好处是不需要下载任何APP进行认证,但是需要你自己记住密钥,密钥不记得了就用恢复码重置密钥,若双双不记得了,向像Github提交忘记密码申请账号找回
public static class TotpHelper { /// <summary> /// 获取TOTP三组验证码 + 距离下一次刷新剩余秒数(GitHub适用) /// </summary> /// <param name="base32Secret">GitHub的base32密钥</param> /// <returns>prev,current,next,remainSeconds</returns> public static TOTPDetailsDto GetTotpWindowCodes(string base32Secret) { byte[] key = Base32Decode(base32Secret); long unixTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); long counter = unixTime / 30; //计算距离下一轮刷新剩余秒数 int remainSeconds = 30 - (int)(unixTime % 30); var prev = ComputeTotpCode(key, counter - 1); var current = ComputeTotpCode(key, counter); var next = ComputeTotpCode(key, counter + 1); return new TOTPDetailsDto { PrePWD = prev, CurrentPDW = current, NextPDW = next, RemainTime = remainSeconds }; } /// <summary> /// 根据counter计算单组TOTP /// </summary> private static string ComputeTotpCode(byte[] key, long counter) { byte[] counterBytes = BitConverter.GetBytes(counter); if (BitConverter.IsLittleEndian) Array.Reverse(counterBytes); using var hmac = new HMACSHA1(key); byte[] hash = hmac.ComputeHash(counterBytes); int offset = hash[hash.Length - 1] & 0x0F; int binary = ((hash[offset] & 0x7F) << 24) | ((hash[offset + 1] & 0xFF) << 16) | ((hash[offset + 2] & 0xFF) << 8) | (hash[offset + 3] & 0xFF); int code = binary % 1000000; return code.ToString("D6"); // D6 保证6位,前面补0 } /// <summary> /// RFC4648 Base32解码,谷歌Authenticator / GitHub TOTP专用 /// </summary> private static byte[] Base32Decode(string input) { const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input)); input = input.ToUpperInvariant().Replace("=", ""); int bitCount = input.Length * 5; byte[] output = new byte[(bitCount + 7) / 8]; int bitPos = 0; foreach (char c in input) { int val = alphabet.IndexOf(c); if (val < 0) throw new FormatException($"非法Base32字符:{c}"); for (int i = 4; i >= 0; i--) { if ((val & (1 << i)) != 0) { int byteIndex = bitPos / 8; int bitIndex = 7 - (bitPos % 8); output[byteIndex] |= (byte)(1 << bitIndex); } bitPos++; } } return output; } public class TOTPDetailsDto { /// <summary> /// 上一个密码 /// </summary> public string PrePWD { get; set; } = string.Empty; /// <summary> /// 当前密码 /// </summary> public string CurrentPDW { get; set; } = string.Empty; /// <summary> /// 下一个密码 /// </summary> public string NextPDW { get; set; } = string.Empty; /// <summary> /// 当前密码剩余时间(s) /// </summary> public int RemainTime { get; set; } } } class Program { /// <summary> /// 生成TOTP规范随机Base32密钥(仅本地测试) /// </summary> public static string CreateRandomBase32Secret(int length = 16) { const string base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; Random random = new Random(); char[] result = new char[length]; for (int i = 0; i < length; i++) { result[i] = base32Alphabet[random.Next(base32Alphabet.Length)]; } return new string(result); } static async Task Main() { // ========== 这里替换为你GitHub的手动设置密钥(Base32) ========== //调用示例 string githubBase32Secret = CreateRandomBase32Secret(); githubBase32Secret = $"2WUYW6CXWYETD6KK";//固定测试密钥 Console.WriteLine("密钥"+githubBase32Secret); var res = TotpHelper.GetTotpWindowCodes(githubBase32Secret); Console.WriteLine($"上一窗口验证码:{res.PrePWD}"); Console.WriteLine($"【当前窗口验证码】:{res.CurrentPDW}(剩余时间是:{res.RemainTime}s)"); Console.WriteLine($"下一窗口验证码:{res.NextPDW}"); Console.WriteLine("按任意键退出"); Console.ReadKey(); } }五、好用工具推荐
1.在线网站
好处是方便,坏处是清理缓存丢密钥,需要自己保存密钥
网址是:https://totp.app/
Online one-time password generator / TOTP (Google Authenticator) Online / 2FA
2.在线App工具
使用苹果手机下载微软官方的Microsoft AuthenticatorApp
3.在线电脑工具
下载使用我开发的工具EasyAuthenticator
链接:
步骤:
1.点击获取密钥
2.在EasyAuthenticator设置密钥,并且保存好密钥
3.输入首个密钥
4.保存你的恢复码
5.大功告成