google验证手机号码无法验证_Google验证器是如何实现的?

4cd674d8eb80cc041ce641f95ceb7d58.png

1. Google验证器应用场景

(1)用户安装手机客户端,生成临时的身份验证码。

(2)用户将临时身份验证码提交到服务器验证身份。

(3)服务器确认用户身份,完成准入。

常见的使用场景:

  • Google Apps验证
  • 公司的软token登录服务器

应用:Authy

2. Google验证器实现原理

Google身份验证系统是通过基于时间的一次性密码算法实现的双因子(2FA)验证,即TOTP(Time-Based One-Time Password)算法。该算法由3部分组成:

  1. 一个共享密钥
  2. 一个基于当前时间的输入
  3. 一个签名函数

2.1 Shared Secret(共享密钥)

用户在手机端进行身份验证的时候,需要获取共享密钥。拿Authy举例,获取的方式包括识别程序扫描给定的二维码(QR)或者直接手动输入,密钥是32位加密的字符串。

(1)扫描QR用户,QR识别的URL链接为:

otpauth://totp/Google%3Ayourname@gmail.com?secret=xxxx&issuer=Google

(2)对于手动输入的用户,Google身份验证系统给出的共享密钥格式为:

xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

步骤如下:

  • 用户开启双因子(2FA)验证后,服务器会生成一个密钥(secret)
  • 服务器提示用户扫描二维码或者手动输入的方式,将密钥保存在用户的手机上。此时,用户和服务器现在都拥有同一把钥匙。
需要注意的是密钥必须跟手机绑定,一旦用户更换手机,需要重新生成全新的密钥
  • 用户登录时,手机客户端Authy使用这个密钥和当前的Unix时间戳,生成一个hash value(h1),有效期默认为30s。用户在有效期内,将这个哈希值提交给服务器。
  • 服务器也使用密钥和当前时间戳,生成一个hash value(h2),将h2和用户提交的h1进行比较,如果两者一致,就能够正常登陆,否则,拒绝登陆。

2.2 Input(Current Time)

简单来说,输入是基于用户手机产生的当前时间,一旦你获取到secret密钥,就不用再与服务器进行通信了。但是这里比较重要的是用户手机时间要准确,因为从算法原理来讲,身份验证服务器会基于同样的时间来重复进行用户手机的运算。进一步来说,服务器会计算当前时间前后几分钟内的令牌,跟用户提交的令牌比较。所以如果时间上相差太多,身份验证过程就会失败。

2.3 Signing Function(签名函数)

签名函数使用的是HMAC-SHA1。HMAC是基于哈希的消息验证码,能够用安全的单向哈希函数(SHA1)来生成签名。

验证算法的原理:只有共享密钥拥有者和服务器才能根据同样的输入(基于时间的)得到同样的输出签名。

hmac = SHA1(secret + SHA1(secret + input))

3. 算法

3.1 首先,使用base32的解码密钥

为了更方便用户输入,谷歌采用了空格和小写的方式表示密钥。但是base32不能有空格而且必须大写,伪代码如下:

original_secret = xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
secret = BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))

3.2 接下来,从当前时间获取输入,即Unix时间戳

input = CURRENT_UNIX_TIME()

一般验证码会有个失效时间,大概30s。这种设计主要是出于方便用户输入考虑,为了实现这种时效性,可以通过整除30的方式来实现。

input = CURRENT_UNIX_TIME() / 30

3.3 最后一步,签名函数(HMAC-SHA1)

伪代码如下:

original_secret = xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
secret = BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))
input = CURRENT_UNIX_TIME() / 30
hmac = SHA1(secret + SHA1(secret + input))
SHA1中的input转换为byte[8]的时候一定要是大端转换。

由于HMAC是个标准长度的SHA1数值,有20-byte,40 hex characters的长度,对于用户来说太长,所以google会根据规则截取6位数字。(也就是我们在Authy中看到的6个数字)

4. 最终的伪代码

original_secret 

5. 代码实现及验证

5.1 举个栗子:Gitlab开启2FA验证 + Authy

(1)拥有一个Gitlab账号

在Account中,Register Two-Factor Authenticator

otpauth://totp/gitlab.com:410534805@qq.com?secret=4nygwpepxigvav6smazcz6574ghc5jvo&issuer=http://gitlab.com (二维码自动识别)

(2)手机端安装Authy App

用Authy扫描Gitlab中的二维码,Authy端就会根据当前时间戳生成一个6位数字的验证码,每隔30s变一次。

将验证码输入到(1)中的Pin code中,完成校验。

3538a73f456d7831b770aed3b9955a2a.png

(3)退出登录,重新登录Gitlab,输入完用户+密码后,会提示进行2FA验证。

3938deb9227636a70c30f1db312b7e74.png

5.2 代码实现

代码详见:https://github.com/robbiev/two-factor-auth/blob/master/main.go

根据Gitlab生成的二维码,使用扫码工具识别出是以下URL

otpauth://totp/gitlab.com:410534805@qq.com?secret=4nygwpepxigvav6smazcz6574ghc5jvo&issuer=gitlab.com

我们知道secret=4nygwpepxigvav6smazcz6574ghc5jvo

接下来,我们运行程序

#会每30s变换一次Pin Code

此时,我们可以看到Authy生成的Pin Code,跟服务器生成的一致。

6. 参考文章

How Google Authenticator Works​garbagecollected.org
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值