2FA与MFA技术学习

一、2FA和MFA

  • 2FA(Two-Factor Authentication):双因子身份验证。

  • MFA(Multi-Factor Authentication):多重因子身份验证,通常两个或更多。

二、2FA的实现方式

本文以TOTP和HOTP为主介绍,U2F以及NFC仅简单介绍。

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

  • 原理:
    • 客户端与服务端之间保存一个秘钥
    • 客户端获取到当期时间戳,将时间戳转为30秒(一般为30—60秒)的计数器
    • 客户端使用秘钥和计数器计算出一次性密码
    • 将密码发送给服务器验证
  • 实现:使用BastiaanJansen/otp-java来实现TOTP算法
1
2
3
4
5
<dependency>
<groupId>com.github.bastiaanjansen</groupId>
<artifactId>otp-java</artifactId>
<version>2.0.2</version>
</dependency>
  • 生成otpauth 并 进行验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void totp() throws URISyntaxException {
// 生成一个共享秘钥 (或者使用你自己的共享秘钥)
byte[] secret = SecretGenerator.generate();

TOTPGenerator totp = new TOTPGenerator.Builder(secret)
.withHOTPGenerator(builder -> {
builder.withPasswordLength(6);
// 还支持SHA256和SHA512
builder.withAlgorithm(HMACAlgorithm.SHA1);
})
// 密码有效时间(单位秒)
.withPeriod(Duration.ofSeconds(30))
.build();

URI uri = totp.getURI("User_Name");
System.out.println(uri);

String code = totp.now();
System.out.println("code:" + code);
// 验证令牌:
boolean isValid = totp.verify(code);
System.out.println("isValid:" + isValid);
}
  • Java生成的otpauth,生成二维码,通过Authenticator App扫描即可绑定
    • otpauth://totp/User_Name?period=30&digits=6&secret=VV3KOX7UQJ4KYAKOHMZPPH3US4CJIMH6F3ZKNB5C2OOBQ6V2KIYHM27Q&issuer=User_Name&algorithm=SHA1
  • 通过Authenticator App生成的OTP
    • f53c5172be1ea02a5c6c96a855def5f
  • Java代码生成的OTP
    • image-20231017123738816

2.2 HOTP(基于事件的一次性密码)

  • 原理:
    • 客户端和服务端之间共享一个密钥。
    • 客户端和服务端都有一个计数器,用于记录已经生成过的密码的次数。
    • 客户端使用密钥和计数器来计算出一个一次性密码HOTP。
    • 客户端将HOTP发送给服务段进行验证。
  • 实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void hotp() throws URISyntaxException {
// 共享密钥,可以是任意字符串,长度一般为8-10个字符 将共享密钥转换为字节数组
byte[] secret = "VV3KOX7UQJ4KYAKOHMZPPH3US4CJIMH6F3ZKNB5C2OOBQ6V2KIYHM27Q".getBytes();
// 创建“HOTPGenerator”实例
HOTPGenerator hotp = new HOTPGenerator.Builder(secret)
// 生成的密码长度
.withPasswordLength(6)
// 加密方式
.withAlgorithm(HMACAlgorithm.SHA256)
.build();

URI uri = hotp.getURI(5, "HTOP_USER");
System.out.println(uri);

String code = hotp.generate(5);
System.out.println("code:" + code);
// 验证令牌:
boolean isValid = hotp.verify(code, 5);
System.out.println("isValid:" + isValid);
}
  • Java生成的otpauth,生成二维码,通过Authenticator App扫描即可绑定
    • otpauth://hotp/HTOP_USER?digits=6&counter=5&secret=VV3KOX7UQJ4KYAKOHMZPPH3US4CJIMH6F3ZKNB5C2OOBQ6V2KIYHM27Q&issuer=HTOP_USER&algorithm=SHA256
  • Java代码生成的OTP
    • image-20231017125403815

2.3 U2F(通用第二因素)

使用USB接口的硬件安全模块,它通过在用户和计算机之间添加硬件安全层来保护用户登录信息。

例如:Yubico、Nitrokey、Feitian等

image-20231017130357031

2.4 NFC(近场通信)

  1. 用户在设备上生成一个密钥,并将密钥存储在安全芯片中。
  2. 当用户需要进行身份验证时,只需将设备靠近读卡器即可。
  3. 读卡器会读取用户的密钥信息,并将其发送到服务器进行验证。
  4. 服务器根据用户提供的密钥信息进行验证,并返回验证结果。

三、总结

TOTP是基于时间戳算法的一次性密码,而HOTP则是基于HMAC算法的一次性密码。

TOTP以客户端和服务端的时间为基础,要求它们能够精确地保持正确的时钟,以便在任何特定时刻生成相同的一次性密码。

HOTP以特定的事件次序和相同的种子值为输入,通过HASH算法运算出一致的密码。

相比TOTP和HOTP,2.3和2.4都需要额外硬件才能实现,而TOTP和HOTP只需要智能手机。

1
2
3
4
5
本文为个人知识学习,非原创!非作者!如本博客有侵权行为,请与我联系。
摘录以下文章,内容根据个人需求有所删减,尊重知识产出,尊重作者知识劳动成果。

链接:https://github.com/BastiaanJansen/otp-java
链接:https://yiyan.baidu.com/