二次验证和验证器APP

二次验证 (2FA) Two-Factor Authentication 是指:在用户名/密码之外,增加一个一次性密码的验证方式。表现形式有很多种,一般有:U盾、手机短信验证码、电话语音验证码、APP或系统弹窗、软件实现(验证器APP)。
二次验证要解决的问题是:用户名/密码是相对固定不变的,如果被窃取(偷看/内存破解/键盘记录/拦截数据传输解密),其它人可以冒充身份。二次验证加入了一个一次性密码以后,这个密码使用一次后即失效,即使使用过程中被窃取也不能被拿来再次通过身份验证。
从这样的原理来看,针对二次验证一次性密码的攻击就是要在生成密码到使用密码之间窃取密码,并抢在用户使用之前用于身份验证。所以现在的各种骗术都是要拿到短信验证码(有的是通过手机木马的方式,有的是通过骗取信任的方式)

分析一下安全性:
1. iOS手机不越狱、安卓手机不解锁的话,短信验证码还是可靠的。这也是目前手机银行APP采用的方案。
2. 如果出境,手机号的方案就不方便了。还是要靠验证器APP。

验证器APP的原理是:
1.生成一个密钥,服务器和用户都知道这个密钥。密钥保管好后,以后不再传输;
2.用密钥+当前时间用一个单向算法生成动态密码。
3.服务器通过动态密码间接验证用户是否持有正确的密钥,进而验证身份。
实际应用中密钥需要保证一定的长度,如:BPPC7YHP2KD2BZFGPGMLZBBOUOO4627H,时间同步按30秒刷新一次,算法使用的是HMAC-SHA1,最终的动态密码是6位数字。
第1步中,密钥可以生成得足够复杂,间接解决了用户喜欢使用弱密码的问题。这一步需要在安全的环境中进行,保证密钥不被泄漏。
整个方案叫做TOTP(Time-based One-time Password 基于时间的一次性密码)。算法本身是公开的(https://tools.ietf.org/html/rfc6238),所以有很多APP可选,比如:Google Authenticator、Authy、Microsoft Authenticator、Tofu等。不同的APP在细节上有一些不同,比如密钥的备份、同步等。

为了方便第1步的实践,一般网站会让你用APP扫一个二维码,它的内容实际是像这样子的:
otpauth://totp/Cloudflare:bob?secret=P72DGTKGGUAN7GOGZFFGGNCP5BCN3445&issuer=Cloudflare 
其中只有密钥部分是关键有用的,其它部分是辅助你记忆的(哪个服务商,哪个用户名
在大多数情况下,这两个信息足够了。不过中国的特殊国情,比如:Amazon.com和Amazon.cn没有区分开,显示的服务商都是Amazon。

几个常见验证器APP的功能对比:
Microsoft Authenticator可以编辑服务商信息,不能编辑用户名信息。
Tofu这两个信息都可以编辑。
Authy只能编辑用户名信息。
Google Authenticator只能编辑用户名信息。

开了二次验证后,登录的时候除了用户名/密码以外,还需要输入一次性密码。(有些网站可以设置常用设备,在常用设备上登录可以免去输入二次验证密码的步骤。使用短信验证码的网站一般只会在有可疑登录的时候要求二次验证)如果验证器APP不在身边,或者手机丢了,又或者升级手机系统把验证器APP保存的密钥删除了,就会很麻烦。
所以开了二次验证以后,密钥的备份就很重要。

Authy是备份在它的服务器上的。用手机号+主密码验证身份。有的人认为它的服务器集中存放了很多人的密钥,容易被重点攻击,不够安全。
Keepass有TOTP的插件(https://github.com/victor-rds/KeeTrayTOTP/),会把密钥和设置(刷新时间间隔、动态密钥长度)保存在一条记录的属性里面。这样即使换了一个环境,没有插件,也可以拿到密钥再计算出动态密码。

Keepass已经保存了用户名/密码,如果再把TOTP密钥保存在里面,万一Keepass数据库的主密码被破,就完全城门大开了。所以TOTP和用户名/密码要分别保存在不同的密码库里,使用不同的主密码,甚至密码库也要分开保存。

我目前没有使用TOTP作二次验证,而是用短信验证码作二次验证的,用了一个专用手机号。这样我只要保管好SIM卡就行了。再加一层保护的话,给SIM卡设置PIN,即使SIM卡丢了也不怕。实在不行还可以凭身份证去营业厅补办SIM卡。

评论

The Hot3 in Last 30 Days

RackNerd VPS搭Hysteria2 HY2梯子 年付 $10.98 1G端口 3T流量 17G存储 1GB内存

强行重装 233boy的sing-box脚本 取消脚本报错退出的逻辑

KV-woker 纯练手项目 保护 _ 开头的 Key VS code 重构 JS 代码 提取代码为函数