双因素认证(2FA)原理介绍及实现

😀 我们常说的认证(authentication)就是在确认用户的身份,是在进行重要操作时的必要手段,譬如网站登录、银行取现等。

使用密码是生活中最常见的认证手段,但是密码是单一因素,不安全,并且很容易被泄露和冒充。今天我们来学习一种更安全的认证方式------双因素认证。

双因素认证的概念

双因素认证(Two-factor authentication,简称 2FA),想要了解2FA,我们首先要知道双因素是指什么。

这里的因素是指证明一个人身份的证据,一般来说可以被分为三种证据。

  • 秘密信息:只有该用户知道、其他人不知道的某种信息,比如密码。
  • 个人物品:该用户的私人物品,比如身份证、钥匙。
  • 生理特征:该用户的遗传特征,比如指纹、相貌、虹膜等等。

认证时使用因素越多,越能证明这个人的身份,身份也就越可靠。

回到我们今天所说的「双因素认证」,就能很清晰地明白含义了,即认证时需要同时两个因素的证据才能通过。譬如:银行卡就是生活中最常见的双因素认证。用户必须同时提供银行卡和密码,才能在ATM取出现金。

双因素认证的设计

常用的双因素组合是密码 + 某种个人物品,比如网上银行的 U 盾。用户插上 U 盾,再输入密码,才能登录网上银行(现在几乎不再使用 U 盾了,U 盾实物见下图)。

但是,用户不可能随时携带 U 盾,手机才是最好的替代品。密码 + 手机就成了最佳的双因素认证方案。很多网站也有这样的要求,在登录账户时,用户通过账号密码登录后,仍需要提供短信发送的验证码,以证明用户确实拥有该手机。

但是,短信是不安全的,通过伪基站就很容易将消息拦截或伪造,同时 SIM 卡也可以被补办。早些时候,凭借身份证就可以补办手机号,犯罪分子会先伪造身份证,再去补办一张户主的手机号码,通过该手机接收验证码,通过验证码认证将钱转走。

由此用短信作为补充因素的双因素认证是相当不可靠的,而我们今天要说的是 TOTP

TOTP 介绍

TOTP 全称为"基于时间的一次性密码"(Time-based One-time Password)。它是国际上公认的可靠解决方案,已经写入国际标准 RFC6238

TOTP的计算步骤:

  1. 用户在安全设置中开启双因素认证,服务器生成一个密钥,可能是二维码的形式(二维码的主要内容就是这个密钥)。

  2. 需要用户记录这个密钥,譬如通过TOTP软件扫描二维码(或者使用其他方式),把密钥保存到用户手机中。这时候,服务器和用户手机中都保存了这个密钥,后面做验证就是基于这个密钥去完成。

  3. 在用户登录时需要输入TOTP的动态验证码,这时手机中TOTP软件生成器就会使用这个密钥和当前时间戳去生成一个哈希,一般有效期为30秒。在这个有效期内,用户都可以使用这个哈希验证码,并将其提交给服务器。

  4. 服务器验证这个哈希验证码,这时候会使用密钥和当前时间戳,生成一个哈希验证码,并与用户提交的哈希验证码进行对比。两者一致才能通过认证。

TOTP 算法

通过TOTP的计算步骤,我们得知了哈希验证码只有30秒有效期,那么手机如何与服务器保持一致呢?

我们可以想到,只要手机和服务器共同维护一个时间计数器,那么在同样的时间计数下,得到的哈希验证码就是一致的。

那么在手机和服务器中如何维持同一个时间计数器呢?接着往下看

scss 复制代码
TC = floor((unixtime(now) − unixtime(T0)) / TS)

在这个公式中,TC 表示一个时间计数器,unixtime(now)是当前 Unix 时间戳(从1970年1月1日开始的计数),unixtime(T0)是约定的起始时间点的时间戳,默认是0,也就是1970年1月1日。TS 则是哈希有效期的时间长度,默认是30秒。

ini 复制代码
TC = floor(unixtime(now) / 30)

由此,只要服务器和手机的时间是同步的,则在这 30 秒以内,TC 的值都是一样的,哈希验证码也就是一样的。

计算哈希验证码

ini 复制代码
TOTP = HASH(SecretKey, TC)
  • HASH就是约定的哈希函数,默认是 SHA-1。

TOTP 分类

TOTP 有硬件生成器和软件生成器之分,但都是采用上面的算法。TOTP 硬件生成器实物如下图。

而TOTP 软件生成器目前市面上有Google Authenticator、Microsoft authenticator、Tofu Authenticator等,界面如下图。

📎 参考文章

相关推荐
杜杜的man29 分钟前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*30 分钟前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu31 分钟前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s32 分钟前
Golang--协程和管道
开发语言·后端·golang
为什么这亚子34 分钟前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
想进大厂的小王1 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea
2402_857589361 小时前
SpringBoot框架:作业管理技术新解
java·spring boot·后端
一只爱打拳的程序猿2 小时前
【Spring】更加简单的将对象存入Spring中并使用
java·后端·spring