Google Authenticator工作原理

Google Authenticator是谷歌推出的一款动态口令工具,旨在解决大家Google账户遭到恶意攻击的问题,在手机端生成动态口令后,在Google相关的服务登陆中除了用正常用户名和密码外,需要输入一次动态口令才能验证成功,此举是为了保护用户的信息安全。那么,Authenticator采用了哪些算法?又是如何实现的?且看本文技术解读。

很多手机用户会使用 Google Authenticator(谷歌身份认证)来生成认证令牌,与传统单因子密码不同,其采用的是更安全的双因子(2FA two-factor authentication)认证。FA是指结合密码以及实物(信用卡、SMS手机、令牌或指纹等生物标志)两种条件对用户进行认证的方法。只需要在手机上安装如此高大上的密码生成应用程序,就可以生成一个随着时间变化的一次性密码,用于帐户验证,而且这个应用程序不需要连接网络即可工作。

实际上Google Authenticator采用的算法是TOTP(Time-Based One-Time Password基于时间的一次性密码),其核心内容包括以下三点:

一个共享密钥(一个比特序列);
当前时间输入;
一个签署函数。
共享密钥

共享密码用于在手机端上建立账户。密码内容可以是通过手机拍照二维码或者手工输入,并会被进行base32加密。

手工密码的输入格式如下:

xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

包含该令牌的二维码的内容是一个URL:

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

时间输入(当前时间)

输入的时间值来自于手机本身,一旦我们获得密钥后,就无需与服务器再进行通信了。但是最重要一点是务必确保手机上的时间是正确的,因为往后的步骤服务器会多次重复使用之前得到的时间值,服务器只会认准这个值。进一步说,服务器会比对所有提交的令牌以确认哪一个是你输入并提交的。

签署

签署所使用的方法是HMAC-SHA1。HMAC的全称是Hash-based message authentication code(哈希运算消息认证码),以一个密钥和一个消息为输入,生成一个消息摘要作为输出,这里以SHA1作为消息输入。使用HMAC的原因是:只有用户本身知道正确的输入密钥,因此会得到唯一的输出。其算法可以简单表示为:

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

事实上,TOTP是HMAC-OTP(基于HMAC的一次密码生成)的超集,区别是TOTP以当前时间作为输入,而HMAC-OTP以自增计算器作为输入,该计数器使用时需要进行同步。

算法

首先,要进行密钥的base32加密。虽然谷歌上的密钥格式是带空格的,不过base32拒绝空格输入,并只允许大写。所以要作如下处理:

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

第二步要获取当前时间值,这里使用的是UNIX time函数,或者可以用纪元秒。

input = CURRENT_UNIX_TIME() 

在Google Authenticator中,input值拥有一个有效期。因为如果直接根据时间进行计算,结果将时刻发生改变,那么将很难进行复用。Google Authenticator默认使用30秒作为有效期(时间片),最后input的取值为从Unix epoch(1970年1月1日 00:00:00)来经历的30秒的个数。

input = CURRENT_UNIX_TIME() / 30

最后一步是进行HMAC-SHA1运算

1.original_secret = xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  

2.secret = BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))  

3.input = CURRENT_UNIX_TIME() / 30  

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

至此,2FA所需的两个因子都已准备就绪了。但是HMAC运算后的结果会是20字节即40位16进制数,应该没有人会愿意每次都输入这么长的密码。我们需要的是常规6位数字密码!

要实现这个愿望,首先要对20字节的SHA1进行瘦身。我们把SHA1的最后4个比特数(每个数的取值是0~15)用来做索引号,然后用另外的4个字节进行索引。因此,索引号的操作范围是15+4=19,加上是以零开始,所以能完整表示20字节的信息。4字节的获取方法是:

1.然后将它转化为标准的32bit无符号整数(4 bytes = 32 bit):

2.large_integer = INT(four_bytes) 

最后再进行7位数(1百万)取整,就可得到6位数字了:

1.large_integer = INT(four_bytes)  

2.small_integer = large_integer % 1,000,000 

这也是我们最后要的目标结果,整个过程总结如下:

1.original_secret = xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  

2.secret = BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))  

3.input = CURRENT_UNIX_TIME() / 30  

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

5.four_bytes = hmac[LAST_BYTE(hmac):LAST_BYTE(hmac) + 4]  

6.large_integer = INT(four_bytes)  

7.small_integer = large_integer % 1,000,000 
也可以用golang库实现

https://github.com/robbiev/two-factor-auth

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对于Google Authenticator(谷歌验证)的密码输入,实际上并没有一个固定的密码。Google Authenticator通过基于时间的一次性密码(TOTP)生成密码来进行账户验证。这种密码是根据事先与服务器约定好的密钥和当前的时间戳来生成的。当用户登录时,他们需要在Google Authenticator应用程序中输入由此算法生成的一次性密码,并将其发送到服务器进行验证。如果生成的一次性密码与服务器计算的密码一致,登录将成功。这种基于时间的算法确保了每个一次性密码只有在短时间内有效,提高了账户的安全性。所以实际上,你需要根据服务器提供的密钥和当前的时间戳,在Google Authenticator应用程序中生成对应的一次性密码,并输入该密码进行验证。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [谷歌验证器 Google Authenticator工作原理](https://blog.csdn.net/weixin_39732991/article/details/110784762)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [谷歌Google authenticator 整合到JAVA项目](https://blog.csdn.net/baidu_38990811/article/details/106002098)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gitxuzan_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值