两步验证(2-step verification)

· Read in about 1 min · (171 Words)
auth work

关于两步验证

两步验证是一种安全措施,用于保护某些资源不被泄露,即使在泄露了密码的情况下。 两步验证有多种方式,主要包括:短信、验证器、电话等方式。本文主要讲述验证器方式的两步验证。

工作原理

使用基于验证器方式的两步验证通常需要另外一部设备(通常是手机,也可能是其它硬件)。 用户在登录系统时,除了输入正常的密码外,还需要输入一个动态生成的密码。 此动态密码由另外一部可信设备提供,具有一个较短的时效性,保证不会重回攻击。

动态密码生成通常有两种算法:TOTP与HOTP。

TOTP(Time-Based One-Time Password)是指基于时间的一次性密码。
HOTP(HMAC-based One-time Password)是指基于计数的一次性密码。

安全令牌硬件(如某些银行的动态密保,游戏账号的密码令牌)通常是基于HOTP方式实现。 其表现为使用专有硬件,为某一特定产品或系统服务。

而当前大多数两步验证使用的是TOTP方式实现,比如Google Authenticator。

TOTP流程

基于TOTP的两步验证流程一般通过需要先绑定,然后随用随验证。

现假设有一系统S,用户A进行两步验证

绑定流程一般如下:

  1. 用户A注册/登录系统S后,S后台生成一个OTP链接,在前端生成并显示该链接的二维码
  2. 用户A用手机通过Google Authenticator之类的验证器G扫描二维码进行绑定
  3. 验证器G会生成动态密码C,用户A将动态密码C输入到系统S的绑定验证框内
  4. 如果系统S后台验证该动态密码C成功,则系统S与验证器G绑定成功。否则,绑定失败。

示意图

验证流程如下:

  1. 用户A通过账号密码登录系统S
  2. 系统S验证账号和密码匹配后,跳转到两步验证页面
  3. 用户A将验证器G里的动态验证码C输入到两步验证页面的验证框中
  4. 系统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]中各部份的意义如下:

  1. otpauth表示OTP认证协议
  2. totp表示使用TOTP算法
  3. Google表示生成此链接的公司或软件名称
  4. [email protected]表示该链接所对应的用户的用户名

而后面一段查询参数中各部份意义如下:

  1. secret是由服务端Base32编码生成的字符串。其内容不重要,只要保证随机性即可,应保证每个用户都拥有一个独立的secret
  2. 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端使用支付宝,通常也可以通过手机支付宝扫页面上二维码进行支付确认。

三、推送认证
当微信桌面端已登录过,保存有信息时,通常会推送一条登录请求给手机微信端,需要在手机端确认。

引用

  1. Google 两步验证
  2. Apple 两步验证
  3. Apple 双重认证

Comments