uncategorized

谷歌两步验证

谷歌验证(Google two-factor Authenticator)通常来讲,身份验证系统都实现了基于时间的一次性密码算法,即著名的TOTP(Time-Based One-Time Password)。该算法由三部分组成:

一个共享密钥(一系列二进制数据)
一个基于当前时间的输入
一个签名函数

共享秘钥

用户需要开启Google Authenticator服务时:

  1. 服务器随机生成一个类似于『DPI45HKISEXU6HG7』的密钥,并且把这个密钥保存在数据库中。
  2. 在页面上显示一个二维码,内容是一个URI地址(otpauth://totp/账号?secret=密钥),如『otpauth://totp/kisexu@gmail.com?secret=DPI45HCEBCJK6HG7』,下图:
    image
  3. 客户端扫描二维码,把密钥『DPI45HKISEXU6HG7』保存在客户端。

基于当前时间的输入

这个输入是基于用户手机时间产生的,一旦用户完成第一步的密钥共享,就和身份验证服务器没有关系了。
但是这里比较重要的是用户手机时间要准确,因为从算法原理来讲,身份验证服务器会基于同样的时间来重复进行用户手机的运算。
用户需要登陆时:

  1. 客户端每30秒使用密钥『DPI45HKISEXU6HG7』和时间戳通过一种『算法』生成一个6位数字的一次性密码,如『684060』。如下图android版界面:
    image
    2.用户登陆时输入一次性密码『684060』。

签名函数

谷歌的签名函数使用了HMAC-SHA1。
HMAC即基于哈希的消息验证码,提供了一种算法,可以用比较安全的单向哈希函数(如SHA1)来产生签名。
这就是验证算法的原理所在:只有共享密钥拥有者和服务器才能够根据同样的输入(基于时间的)得到同样的输出签名。伪代码如下:

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

服务器端使用保存在数据库中的密钥『DPI45HKISEXU6HG7』和时间戳通过同一种『算法』生成一个6位数字的一次性密码
如果算法相同、密钥相同,又是同一个时间(时间戳相同),那么客户端和服务器计算出的一次性密码是一样的。服务器验证时如果一样,就登录成功了。