个人技术日常分享

深入解读 MFA 和 TOTP 的实现原理与应用

2024/11/20

前言

前段时间发现自己的aliyun账号存在异常登录,吓的我赶紧改了密码开启了MFA多因素认证。同时,我把github等一干支持MFA的应用都开启了MFA。但是这也给我造成了困扰。每次登录都要拿出手机看看手机上的安全码,感觉有点麻烦。
所以我尝试自己用TOTP来实现一个PC版的MFA,不再依赖手机。
web
终于不用掏手机了。。。

提到各种概念,部分老铁可能有些陌生。但是下面github的界面想必大家都比较熟悉,没错,这就是我们今天要聊的东西。
github

现代数字化时代,密码泄露事件频发,传统的单一密码保护方式已无法满足安全需求。多因素认证(MFA, Multi-Factor Authentication)因其能够显著增强账户安全性,成为越来越多系统的必备安全功能。其中,基于时间的一次性密码(TOTP, Time-Based One-Time Password)是 MFA 的重要实现方式之一。本文将深入解读 TOTP 的原理,并展示其具体实现。


什么是 MFA 和 TOTP?

MFA(多因素认证)

多因素认证是一种验证用户身份的方法,它需要用户提供两个或更多独立的身份验证因素,常见的三种验证因素为:

  1. 知识因素:用户知道的内容,如密码或 PIN。
  2. 拥有因素:用户拥有的内容,如手机、硬件令牌。
  3. 生物因素:用户本身的特性,如指纹、面部识别。
    通过组合不同的验证因素,MFA 能够显著降低因密码泄露带来的风险。

TOTP(基于时间的一次性密码)

TOTP 是一种动态生成的密码,基于:

  • 共享密钥:系统和用户共享的一个随机密钥。
  • 时间步长:通常为 30 秒,密码每 30 秒更新一次。
    TOTP 密码不可预测且短时间内失效,非常适合作为 MFA 的第二验证因素。

TOTP 的工作原理

标准流程

  1. 共享密钥的生成与分发:

    • 系统生成一个随机的密钥(通常使用 Base32 编码),通过二维码等方式分发给用户。
    • 用户将密钥输入到支持 TOTP 的认证应用(如 Google Authenticator)。
  2. 时间步计算:

    • 当前时间戳(以秒为单位)除以步长(如 30 秒),得到当前的计数器值。
  3. HMAC 运算:

    • 使用共享密钥和计数器值,通过 HMAC-SHA1 算法生成哈希值。
  4. 动态截取:

    • 从哈希值中动态截取 4 字节数据,确保结果随机性。
  5. 生成动态密码:

    • 将截取的数据取模(通常为 10^6),得到一个 6 位数字密码。
  6. 验证:

    • 系统与用户计算出的 TOTP 密码进行比较,若匹配,则验证通过。

TOTP密钥的保护

根据上面TOTP的工作原理我们知道,TOTP里面系统和用户共享一个密钥,一旦密钥泄露,就会导致用户账户的安全风险。针对这个问题,一般可以采取以下措施来降低风险:

  1. 减少密钥泄露的风险

    • 单次展示原则:用户完成绑定后,密钥不再显示,这样即使有人在之后访问用户账户,也无法通过查看页面或接口窃取密钥。
    • 防止截屏泄露:用户可以在绑定时生成密钥的二维码,但绑定完成后,页面不再提供密钥或二维码,减少因截屏或日志记录造成的泄露风险。
  2. 补救措施
    由于密钥只展示一次,丢失密钥的用户可能会面临绑定无法使用的问题。为此,网站通常会提供以下补救机制:

    • 备用验证方法:
      • 提供备用的一次性恢复码(Recovery Codes),通常是几个固定的静态代码,用户可以在 TOTP 无法使用时输入。
      • 提供其他备选验证方式(如短信验证、电子邮件验证)。
    • 重新绑定机制:
      • 用户可以通过验证其他身份信息(如身份证、手机号等)重新绑定 TOTP 密钥。
      • 一些高安全性网站会要求用户提交更详细的验证信息(如人脸识别)来重置密钥。

TOTP 的实现原理

以下是用 C# 实现 TOTP 的核心代码,展示从 Base32 解码到动态密码生成的完整流程。

  1. Base32 解码
    TOTP 密钥通常使用 Base32 编码,需先解码为原始字节。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static byte[] Base32Decode(string base32)
{
// 示例解码实现
const string base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
base32 = base32.TrimEnd('=').ToUpper();
List<byte> bytes = new List<byte>();

int buffer = 0, bitsLeft = 0;
foreach (char c in base32)
{
if (!base32Chars.Contains(c))
throw new FormatException("Invalid Base32 character.");
buffer = (buffer << 5) | base32Chars.IndexOf(c);
bitsLeft += 5;

if (bitsLeft >= 8)
{
bytes.Add((byte)(buffer >> (bitsLeft - 8)));
bitsLeft -= 8;
}
}

return bytes.ToArray();
}
  1. 获取计数器值
    计数器值通过当前时间计算得出,单位为 30 秒。
1
2
3
4
5
6
7
8
9
10
11
12
long GetCounter()
{
return DateTimeOffset.UtcNow.ToUnixTimeSeconds() / 30;
}

byte[] GetCounterBytes(long counter)
{
byte[] bytes = BitConverter.GetBytes(counter);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes); // 转换为大端序
return bytes;
}
  1. HMAC 计算与动态截取
    使用 HMAC-SHA1 算法生成哈希值,并截取动态密码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
string GenerateTOTP(string secretKey, int passwordLength = 6)
{
byte[] keyBytes = Base32Decode(secretKey);
long counter = GetCounter();
byte[] counterBytes = GetCounterBytes(counter);

using var hmac = new HMACSHA1(keyBytes);
byte[] hash = hmac.ComputeHash(counterBytes);

// 动态截取
int offset = hash[^1] & 0x0F;
int binaryCode = ((hash[offset] & 0x7F) << 24) |
((hash[offset + 1] & 0xFF) << 16) |
((hash[offset + 2] & 0xFF) << 8) |
(hash[offset + 3] & 0xFF);

int otp = binaryCode % (int)Math.Pow(10, passwordLength);
return otp.ToString(new string('0', passwordLength)); // 补齐前导零
}
  1. 示例完整调用
    以下代码生成一个 6 位动态密码。
1
2
3
string secretKey = "xxxxxxxxxxx"; // Base32 编码的密钥
string totp = GenerateTOTP(secretKey);
Console.WriteLine($"当前 TOTP 动态密码为: {totp}");

示例完整调用

TOTP 的实际应用

常见场景

  • 账户登录保护:结合密码一起验证,提高安全性。
  • 交易确认:确保关键操作的合法性。
  • 设备绑定:保护设备认证过程。

主流实现工具

  • 手机应用:Google Authenticator、Microsoft Authenticator。
  • 服务器支持:多语言库(如 Python 的 pyotp、Java 的 OtpAuth)。

TOTP 的优缺点

优点

  1. 安全性高:密码定期更新,短时间内有效。
  2. 易用性好:无需额外硬件,使用手机即可。
  3. 实现简单:基于开源算法和规范,易于集成。

缺点

  1. 时间同步要求:客户端与服务器需时间一致。
  2. 丢失风险:若用户丢失密钥或设备,可能导致无法验证。

总结

TOTP 是多因素认证中的关键技术,通过动态密码提高安全性,广泛应用于各类系统。理解其原理并掌握实现技术,可以帮助开发者更好地保障用户账户安全。希望本文的讲解与示例能为您搭建 TOTP 功能提供帮助!
在下一步的实践中,你是否准备好为你的应用添加 MFA 支持?或者尝试将 TOTP 整合到你的项目中?

欢迎分享你的实现和经验,如果需要更具体的内容,欢迎随时讨论! 😊

CATALOG
  1. 1. 前言
  2. 2. 什么是 MFA 和 TOTP?
    1. 2.1. MFA(多因素认证)
    2. 2.2. TOTP(基于时间的一次性密码)
  3. 3. TOTP 的工作原理
  4. 4. TOTP密钥的保护
  5. 5. TOTP 的实现原理
  6. 6. TOTP 的实际应用
  7. 7. TOTP 的优缺点
  8. 8. 总结