前言
好久没登陆Github了,发现Github需要经过2FA认证才能正常使用功能。Github推荐用可以用认证软件来扫描二维码来生成动态密码,或者利用secretKey专属密钥来生成动态密码。
我试了试用github推荐的软件,但是他们要么要付费,要么国内手机号无法注册,行不通呀根本行不通。
所以我就在百度里面搜免费2FA动态密码生成器,真的找到了好心人提供的生成器,输入动态密码后丝滑进入Github。
2FA认证是什么
2FA,2 Factor Authentication,双因子验证/双因素验证,是一种安全密码验证方式。区别于传统的密码验证,由于传统的密码验证是由一组静态信息组成,如:字符、图像、手势等,很容易被获取,相对不安全。2FA是基于时间、历史长度、实物(信用卡、SMS手机、令牌、指纹)等自然变量结合一定的加密算法组合出一组动态密码,一般每60秒刷新一次。不容易被获取和破解,相对安全。 ————以上来自百度百科
在Github这里,2FA采用的双因子一般是时间和个人密钥。Github会根据时间和账号的密钥比对我们填写的动态密码的一致性,一致才能通过验证。
PS:
- Github中动态密码长度为6位;
- Github中动态密码的有效期为30s,也就是说一次性密码每半分钟会变化。
TOTP和HOTP
TOTP(Time-Based One-Time Password Algorithm) 是基于时间的一次性密码算法,可以根据时间因子和密钥生成一次性密码。TOTP算法是基于HOTP算法的,HOTP算法是根据计数器(移动因子)和密钥生成一次性密码。
HOTP
算法公式:HOTP(K,C) = Trancate(HMAC-SHA-1(K,C))
- K:密钥,两端之间共享,不同的用户密钥应该保证唯一且不同
- C:计数器(移动因子),是一个8字节的值
- Digit:一次性密码的位数
HOTP算法是根据计数器(移动因子)和密钥生成一次性密码。
在经过 HMAC-SHA-1
算法用 密钥K 加密 计数器C 后,我们会得到20个字节的十六进制字符串。
Trancate
算法会对加密得到的十六进制字符串进行处理。首先会选取最后1个字节的16进制串,将其转化为十进制数字offset; 然后会从offset开始选取4个字节的字符串,将其转化为十进制数字;最后会根据 Digit位数 对十进制数字取模,获取最后几位数字,如果位数不够就在前方补0。
TOTP
算法公式:TOTP(K,T) = HOTP(K,(T-T0)/X)
- K:密钥,两端之间共享,不同的用户密钥应该保证唯一且不同
- T:当前时间戳(以秒为单位)
- T0: 初始时间戳,一般为0
- X:时间步长,一般为30s、60s,这里是30s
- Digit:一次性密码的位数
从TOTP算法公式可以看到,我们只需要获取时间因子,将时间因子替换HOTP中的计数器即可。
JavaScript实现代码
第一步:密钥解码
Github 2FA认证提供的是经过base32(RFC3548)
编码后的secretKey,所以在这里我们需要对其进行解码,解码的encoding类型选择RFC3548
。
因为Node crypto中的加密的参数需要传递binaryLike形式的值,所以解码的内容我们要用Buffer来进行接收。
1 | js复制代码const secret = 'Github 2FA认证提供的经过base32(RFC3548)编码后的secretKey'; // 这是你的秘钥,需要保密 |
第二步:实现HOTP
1 | js复制代码// 生成HMAC-based One-Time Password (HOTP) |
第三步:获取和处理时间戳
1 | js复制代码// 获取当前时间的时间戳,并以时间步长划分为计数器 |
第四步:得到TOTP动态密码
1 | js复制代码// 生成 TOTP |
全部代码
1 | js复制代码const crypto = require('crypto'); |
参考文档
本文转载自: 掘金