一文读懂 GitHub 2FA:TOTP 密钥、验证码与恢复码(含免下载验证源码)
一、第一步申请密钥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 namebase32SecretGitHub的base32密钥/param /// returnsprev,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 / 2FA2.在线App工具使用苹果手机下载微软官方的Microsoft AuthenticatorApp3.在线电脑工具下载使用我开发的工具EasyAuthenticator链接步骤1.点击获取密钥2.在EasyAuthenticator设置密钥并且保存好密钥3.输入首个密钥4.保存你的恢复码5.大功告成