两步验证(2-step verification)
关于两步验证
两步验证是一种安全措施,用于保护某些资源不被泄露,即使在泄露了密码的情况下。 两步验证有多种方式,主要包括:短信、验证器、电话等方式。本文主要讲述验证器方式的两步验证。
工作原理
使用基于验证器方式的两步验证通常需要另外一部设备(通常是手机,也可能是其它硬件)。 用户在登录系统时,除了输入正常的密码外,还需要输入一个动态生成的密码。 此动态密码由另外一部可信设备提供,具有一个较短的时效性,保证不会重回攻击。
动态密码生成通常有两种算法:TOTP与HOTP。
TOTP(Time-Based One-Time Password)是指基于时间的一次性密码。
HOTP(HMAC-based One-time Password)是指基于计数的一次性密码。
安全令牌硬件(如某些银行的动态密保,游戏账号的密码令牌)通常是基于HOTP方式实现。 其表现为使用专有硬件,为某一特定产品或系统服务。
而当前大多数两步验证使用的是TOTP方式实现,比如Google Authenticator。
TOTP流程
基于TOTP的两步验证流程一般通过需要先绑定,然后随用随验证。
现假设有一系统S
,用户A
进行两步验证
绑定流程一般如下:
- 用户
A
注册/登录系统S
后,S
后台生成一个OTP链接,在前端生成并显示该链接的二维码 - 用户
A
用手机通过Google Authenticator之类的验证器G
扫描二维码进行绑定 - 验证器
G
会生成动态密码C
,用户A
将动态密码C
输入到系统S
的绑定验证框内 - 如果系统
S
后台验证该动态密码C
成功,则系统S
与验证器G
绑定成功。否则,绑定失败。
验证流程如下:
- 用户
A
通过账号密码登录系统S
- 系统
S
验证账号和密码匹配后,跳转到两步验证页面 - 用户
A
将验证器G
里的动态验证码C
输入到两步验证页面的验证框中 - 系统
S
对验证码C
进行验证,如果成功,如登录成功,否则失败
TOTP实现
可以按照上面所述流程,一步步来进行实现。 下面主要介绍几个关键部份。
OTP链接
OTP链接格式: otpauth://TYPE/LABEL?PARAMETERS
。
具体可参考Google Authenticator URI
示例:otpauth://totp/Google:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Google
其中,前面一段otpauth://totp/Example:[email protected]
中各部份的意义如下:
otpauth
表示OTP认证协议totp
表示使用TOTP算法Google
表示生成此链接的公司或软件名称[email protected]
表示该链接所对应的用户的用户名
而后面一段查询参数中各部份意义如下:
secret
是由服务端Base32编码生成的字符串。其内容不重要,只要保证随机性即可,应保证每个用户都拥有一个独立的secret
。issuer
表示生成此链接的公司或软件名称,应与前一段中相应部份一致。
动态验证码生成
动态验证码的生成算法是公开的,可以到此处进行查处:RFC6238
下面给出Go语言版本示例:
// 6位数字动态验证码
var digits = 6
// secret 即为otpauth链接中的secret
// timeValue 为当前unix时间除以验证码失效时间(通常为30s)
func computeCode(secret string, timeValue int64) string {
key, err := base32.StdEncoding.DecodeString(secret)
if err != nil {
return ""
}
hash := hmac.New(sha1.New, key)
err = binary.Write(hash, binary.BigEndian, timeValue)
if err != nil {
return ""
}
h := hash.Sum(nil)
offset := h[len(h)-1] & 0x0f
val := ((int(h[offset]) & 0x7f) << 24) |
((int(h[offset+1] & 0xff)) << 16) |
((int(h[offset+2] & 0xff)) << 8) |
(int(h[offset+3]) & 0xff)
otp := int64(val) % int64(math.Pow10(digits))
code := fmt.Sprintf(fmt.Sprintf("%%0%dd", digits), otp)
return code
}
两步验证的优缺点
两步验证的优点:
- 系统的安全性提高,即使其它网站泄露了用户的明文密码,仍可以保证用户账户不受攻击。
- 动态按时间生成验证码,防止重放攻击。
两步验证的缺点:
- 复杂度提高。用户不仅需要输入密码,还需要输入动态验证码。
- 需要另一个可信设备。即默认用户在绑定时候所使用的设备是安全的。
- 当验证器不可用时(设备丢失或不在身边),无法登录。
- 适合web端登录,不适合移动应用登录
其它验证方式
一、短信认证
短信验证码方式可能是当前中国各大厂商用得最多的一种验证方式。
在用户绑定某个手机号后,将用户与此手机号关联。在有需要进行二次验证的地方,
发送二次验证码短信,用户接收短信并输入该验证码。
二、扫码认证
这在微信登录桌面端与web端的唯一方式。
如果你在桌面web端使用支付宝,通常也可以通过手机支付宝扫页面上二维码进行支付确认。
三、推送认证
当微信桌面端已登录过,保存有信息时,通常会推送一条登录请求给手机微信端,需要在手机端确认。