ArcBlock 课堂 ⑥ | 多步验证那些事 (全程视频 + 文字)
今天上午 8:00(美国太平洋时间 23 日下午 5:00),ArcBlock Technical Learning Series 第五期“多步验证那些事”, 由 ArcBlock 软件工程师 孙博山 讲授。
# 讲座全程视频
# 讲座全程文字
现如今,越来越多的网站开启了多步验证模式进行登录。在ArcBlock,我们开发的BlockAuth模块就很好地支持了MFA,让开发者可以很容易在自己开发的区块链应用中使用多步验证来提高安全性。
开启验证时候的二维码到底藏了什么不能说的秘密?手机上身份验证器的核心功能只要6行代码就能实现?多步验证的过程中蕴藏了那些有趣的密码学原理?多步验证安全吗?如何破解多步验证?本文将和你聊聊多步验证那些事。
什么是多步验证?
多步验证即Multi-Factor Authentication(MFA),顾名思义,就是需要进行多步的验证。如果只验证两步那就叫两步验证Two-Factor Authentication(2FA)。
两步验证举个例子。当我们登录github的时候首先输入用户名密码进行第一步验证;接下来在手机上的身份验证器app上输入一个生成的六位数密码进行第二步验证,之后便可顺利登陆。
多步验证背后用到了不少密码学的知识,还有一系列rfc的规范。
一次性密码otp
我们把时间回到1998年,ietf发布了rfc 2289。这套规范定义了一次性密码(one-time password, otp)。为啥要一次性密码呢?因为当用户通过用户名和密码进行登录时,如果密码一旦被获取,则黑客可以用该密码进行登录,这个叫重放攻击。如何避免重放攻击呢?用一次性密码就行了。一次性密码就像一次性筷子一样,用完扔掉即可,别人捡起来也没啥用。
MD5 ENCODINGSPass Phrase Seed Cnt Hex Six Word Format
====================================================
This is a test. TeSt 0 9E87 6134 D904 99DD INCH SEA ANNE LONG AHEM TOUR
This is a test. TeSt 1 7965 E054 36F5 029F EASE OIL FUM CURE AWRY AVIS
This is a test. TeSt 99 50FE 1962 C496 5880 BAIL TUFT BITS GANG CHEF THY
AbCdEfGhIjK alpha1 0 8706 6DD9 644B F206 FULL PEW DOWN ONCE MORT ARC
AbCdEfGhIjK alpha1 1 7CD3 4C10 40AD D14B FACT HOOF AT FIST SITE KENT
AbCdEfGhIjK alpha1 99 5AA3 7A81 F212 146C BODE HOP JAKE STOW JUT RAP
OTP's are good correct 0 F205 7539 43DE 4CF9 ULAN NEW ARMY FUSE SUIT EYED
OTP's are good correct 1 DDCD AC95 6F23 4937 SKIM CULT LOB SLAM POE HOWL
OTP's are good correct 99 B203 E28F A525 BE47 LONG IVY JULY AJAR BOND LEE
这是rfc里给的一个例子。当服务器选定一个密码、种子和计数器时,会生成一个固定长度的二进制数,通过查表得到6个由大写字母组成的字符串,此为一次性密码。用户输入这些字符串来进行登录,用后即弃。服务器的计数器改变,下次再登录会生成另一个一次性密码。
98年那会互联网刚兴起,有个用户名密码登录就不错了,用一次性密码登录还不是很流行,而且用户每次要输入6个英文单词,比较麻烦。于是乎2005年ietf又发布了一套rfc 4226定义了基于hmac的一次性密码(hmac-based one-time password, hotp)。hmac又是什么鬼?
hamc
直接讲hmac是什么会比较没有上下文,我们先问自己一个问题,我们为什么需要哈希函数?
假设alice要向bob发送一条消息show me the money
。当bob收到该消息的时候,他怎么知道这条消息在传送的过程中没有被人篡改过?于是他和alice商量了一下,发消息时,不仅发送消息,再附加上一条该消息的哈希值。哈希值就是对于任意输入,哈希函数会生成一个固定长度的输出。当bob收到消息的时候,他也进行一次哈希计算,如果他算出来的哈希值和alice发过来的哈希值匹配的话,则表示该消息没有被篡改过。
show me the money
alice ----------------------> bob3f3a323ba2bc
但是这样会有一个问题,假设eve在监听alice与bob的通讯,她可以改动alice发送的消息成show me the honey
,然后她把改过的消息的哈希值算出来附加出去发给bob。当bob收到消息进行哈希计算验证一下,发现和eve发过来的哈希值是一致的。于是bob认为这条消息是没被篡改过的。但是这其实并不是alice发的原始消息。
show me the money show me the honey
alice ------------------> eve -----------------> bob3f3a323ba2bc 37954357d876
也就是说,单靠哈希值只能保证数据的完整性,但却不能保证数据的真实性,因为任何人都可以计算哈希值。那么有什么方法能既保证数据完整性,又保证数据真实性呢?
一个可能的解决方案
我们还是来发送show me the money
这条消息,但是这次我们选一个密钥rA9
。算法很简单,把密钥和要发送的信息连起来,算一次哈希;接着把密钥和刚才算出的哈希连起来,再算一次哈希。我们把第二次的哈希值和消息一起发送给bob。如下图所示
sharA9show me the money -------> f023a7d109f1sharA9f023a7d109f1 -------> b15c701d5e63show me the moneyalice -----------------------> bobrA9 b15c701d5e63 rA9
我们假设alice和bob都有该密钥rA9
,当bob收到消息和哈希的时候,也做两次哈希,比较一下,如果一致的话,就证明消息不仅没有篡改过,而且发过来的人有rA9
这个密钥,也就是说是从alice发来的。
如果此时eve在中间监听,她可以把消息篡改,但是因为她没有密钥rA9
,所以她无法计算出来新的哈希值。所以当bob收到消息时验证一下会发现哈希不一致,于是他可以得出结论,该消息被篡改过了。
show me the money show me the honeyalice -----------------> eve ----------------> bobrA9 b15c701d5e63 b15c701d5e63 rA9233999963a1d
hotp
刚才描述的算法,就是hmac的算法。当我们知道这个之后,我们可以描述一下基于hmac的一次性密码(hotp)的算法。
rA9hmac(sha,"rA9","0000000000000000")00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19d8 41 ef 1c 96 ac 02 0c d1 a3 32 06 15 58 ec 69 4d d2 3f 32*** ** ** ** 2ef 1c 96 ac1110 1111 0001 1100 1001 0110 1010 1100110 1111 0001 1100 1001 0110 1010 11001864144556144556
算法如上图所示,首先选定一个密钥rA9
。用hmac算法计算出一个消息验证码。这里我们不再用show me the money,而是用一个32位的整数,上面的例子是用0来计算。算出来一个20字节的验证码,我们取最后一个字节的最后半个字节,也就是2,找到索引2之后的4个字节,也就是ef 1c 96 ac
,把该32位用二进制表示出来,之后去掉最左边一位的符号位,剩下31位,把该二进制对应的十进制写出来就是1864144556
,取末尾的6位既是最后结果144556
。这个数字就是我们平日用身份验证器生成的6位数一次性密码。
totp
基于hmac的一次性密码需要用一个整数作为参数,服务器和客户端之间需要对这个计数器进行同步,那么我们更加常用的一次性密码则是基于时间的(time-based otp, totp)。
时间在计算机中的存储方式其实就是一个整数,unix时间表示从1970年1月1日0点0时0分开始算起到当前时间所经过的秒数。整个totp算法如下
unix epoch time1970-01-01 00:00:00 02018-10-23 17:00:00 15403140002038-01-19 03:14:07 21474836471901-12-13 20:45:52 -2147483648hotp("rA9",1540314000/30)386452
把当前时间的unix时间计算出来,除以30后传给hotp函数即可。为什么要除以30呢?因为用户输入这个六位数密码需要时间,给个30秒时间应该足够了,30秒过后这个一次性密码就失效了。
如何交换密钥
还记得之前的密钥rA9
吗?服务器和用户之间是如何交换该密钥的?这就是启动多步验证时候出现的二维码里面的内容。
该二维码是一个叫做uri密钥的格式的编码,长这样
otpauth://totp/GitHub:hellokitty?secret=4fakhx6cibvwwngp&issuer=GitHub
其中的secret就是服务器生成的密钥的base32编码。
一个简单身份验证器的实现
mfa.erltotp(Key0) ->T = calendar:datetime_to_gregorian_seconds(calendar:now_to_datetime(erlang:timestamp())) - ?epoch,Key = decode32(string:uppercase(Key0)),hotp(Key,T div 30).hotp(Key,C) -><<_:156,Sz:4>> = Hmac = crypto:hmac(sha,Key,<<C:64>>),<<_:Sz/binary,_:1,N:31,_/binary>> = Hmac,N rem 1000000.
这是一个totp/hotp的Erlang实现,核心部分只要6行代码,跑一下看看
$ cat ~/.mfa/config
{github,"somerandpassword"}.
{gitlab,"somecoolpassword"}.
{google,"somegoodpassword"}.$ escript mfa.erl
github: 583309, valid in 26s
gitlab: 166210, valid in 26s
google: 704368, valid in 26s
多步验证安全吗?
我们可以看到,实现多步验证并不困难,那么多步验证到底有多安全?我们可以看看如何破解多步验证。因为多步验证的核心其实就是hmac,破解hmac的唯一方法就是用暴力破解密钥。我们可以通过写一个小程序来模拟破解过程。
先随机生成一个3字节长的密钥,再通过暴力算法计算,用1个CPU大约16秒可以破解。
$ erl1> hack:run().
Key is <<91,101,252>>, hotp for 73 is 076127potential key found <<12,243,176>>, hotp is 076127
potential key found <<41,163,60>>, hotp is 076127
potential key found <<54,214,149>>, hotp is 076127
potential key found <<57,134,46>>, hotp is 076127
potential key found <<57,206,238>>, hotp is 076127
potential key found <<68,189,61>>, hotp is 076127
potential key found <<70,78,253>>, hotp is 076127
potential key found <<90,172,149>>, hotp is 076127
potential key found <<91,101,252>>, hotp is 076127
potential key found <<96,226,141>>, hotp is 076127
...*** found key <<91,101,252>> in 16s ***
因为是用Erlang,所以可以稍微修改一下程序,用全部的CPU来进行破解
$ erl1> phack:run(3).
Started 12 worker processes.
Random generated key is <<154,226,246>>, hotp for 360 is 917202potential key <<22,72,233>> found by worker <0.172.0>, hotp is 917202
potential key <<67,6,87>> found by worker <0.170.0>, hotp is 917202
potential key <<110,133,18>> found by worker <0.168.0>, hotp is 917202
potential key <<153,173,223>> found by worker <0.166.0>, hotp is 917202
potential key <<197,0,181>> found by worker <0.164.0>, hotp is 917202
potential key <<154,226,246>> found by worker <0.166.0>, hotp is 917202key <<154,226,246>> found by worker <0.166.0> in 1s
在这里,我们在一个6核笔记本上跑一下,等同于12个CPU,速度快了12倍,大约1秒就破解了。
当然破解的只是3个字节的密钥。如果我们尝试破解4个字节:
2> phack:run(4).
Started 12 worker processes.
Random generated key is <<81,10,150,35>>, hotp for 375 is 655173potential key <<170,170,211,211>> found by worker <0.111.0>, hotp is 655173
potential key <<64,3,113,77>> found by worker <0.116.0>, hotp is 655173
potential key <<106,175,21,120>> found by worker <0.114.0>, hotp is 655173
potential key <<0,5,110,147>> found by worker <0.119.0>, hotp is 655173
potential key <<149,93,101,149>> found by worker <0.112.0>, hotp is 655173
potential key <<170,179,226,52>> found by worker <0.111.0>, hotp is 655173
potential key <<213,98,135,55>> found by worker <0.109.0>, hotp is 655173
potential key <<0,21,166,137>> found by worker <0.119.0>, hotp is 655173
potential key <<149,107,68,31>> found by worker <0.112.0>, hotp is 655173
...key <<81,10,150,35>> found by worker <0.116.0> in 849s
花了大概14分钟。每增加一个字节,就相当于增加2^8=256倍破解的难度。下表展示了在一个笔记本上破解mfa要花的时间。
key length bits crack time1 8 ~0s2 16 ~0s3 24 ~16s4 32 ~1.1h5 40 ~11.7d6 48 ~8.2y7 56 ~2099y8 64 ~537ky9 72 ~137my10 80 ~35kmy
可以看到,10字节的密钥通过暴力根本无法破解。目前大多数网站都会用至少10个字节来作为服务器随机生成的密钥。
以上所有的代码都可以在 github 上找到 https://github.com/sunboshan/mfa。
主 讲
小 山
ArcBlock 软件工程师
● 毕业于北航软件学院 最擅长的语言是中文和Erlang
● 拜师Erlang之父Joe Armstrong本人 得秘传二郎宝典一本
● 曾在Code BEAM SF担任讲员
● 喜爱思考事物的本质 偶像是一名厨子
报名听课,请点击文末左下角 “阅读原文” 登录注册:
https://hack.arcblock.io/learning/
ArcBlock 课堂 ① | Intro to GraphQL and Absinthe
ArcBlock 课堂 ② | Intro to Ethereum Smart Contract
ArcBlock 课堂 ③ | Intro to AWS Data Pipeline Services
ArcBlock 课堂 ④ | Intro to AWS Athena
ArcBlock 课堂 ⑤ | What is AWS Kinesis
ArcBlock 课堂预告 | 是的,我们将开放大部分技术讲座
相关阅读:
ArcBlock 课堂预告 | 是的,我们将开放大部分技术讲座
ArcBlock 课堂 ① | Intro to GraphQL and Absinthe
ArcBlock 课堂 ② | Intro to Ethereum Smart Contract
ArcBlock 课堂 ③ | Intro to AWS Data Pipeline Services
ArcBlock 课堂 ④ | Intro to AWS Athena
ArcBlock 课堂 ⑤ | What is AWS Kinesis
ArcBlock 博客 | 北京黑客马拉松小记
ArcBlock 黑客松 ③ | 360分钟11 个DApp 北京黑客创意令人大开眼界
ArcBlock 北京黑客松,你来不来?
ArcBlock 黑客松 ② | 新 SDK 亮相 黑客应用质量更高
ArcBlock 活动 | 首场内测版黑客马拉松成功举行
ArcBlock 博客 | Exchange 服务的工作流程以及如何集成到 OCAP 服务
ArcBlock 博客 | OCAP超简易集成攻略(Android 篇)
ArcBlock 博客 | OCAP 超简易集成攻略( iOS 版篇)
ArcBlock 博客 | 浅析数据对区块链行业发展的重要性
ArcBlock 博客 | 开放链访问协议为何采用 GraphQL
ArcBlock 博客 | 如何解析 BITCOIN 的数据
ArcBlock 博客 | 30 天 21 个版本 OCAP Playground 都经历了哪些变化?
ArcBlock 博客 | 如何在几十个 Repo 中游刃有余?
ArcBlock 博客 | OCAP Playground 入门指南
ArcBlock 分享 | 冒志鸿:公链性能焦虑是被EOS忽悠了
ArcBlock 分享 | 冒志鸿:从互联网、移动互联网到区块链,20年方法论总结
ArcBlock 分享 | 从OCAP到Blocklet,为传统开发者打开迈向区块链的大门
ArcBlock 分享 | OCAP Playground让区块链开发变得更友好
更多ArcBlock区块基石信息,可关注以下渠道了解:
Twitter | https://twitter.com/ArcBlock_io
Instagram | https://www.instagram.com/arcblock/
Facebook | https://www.facebook.com/arcblock.io/
Telegram | https://t.me/ArcBlock
LinkedIn | https://www.linkedin.com/company/18355951/
Reddit | https://www.reddit.com/r/arcblock/
Medium | https://medium.com/arcblock
微博 | https://weibo.com/realArcBlock
微信群 | 加拉群小助手:Ddchain
电报群 | Telegram groups:
Telegram(English): https://t.me/ArcBlock
Telegram(繁体中文): https://t.me/ArcblockAsian
↙ 点击登陆 报名听课
ArcBlock 课堂 ⑥ | 多步验证那些事 (全程视频 + 文字)相关推荐
- 连接一个HTTPS网站的前300毫秒,都发生了什么? | ArcBlock 课堂预告
ArcBlock Technical Learning Series 第二十期 HTTPS 介绍 下周三,3 月 13 日下午 1:30 (美国太平洋时间 12 日下午 21:30 时),由 Arc ...
- ABT CrossChain: 跨链解决方案 123 | ArcBlock 课堂
7 月 13 日下午,由 ArcBlock 区块基石与无涯社区.链闻.Blockmanity 联合举办的「2019 Blockchain Odyssey 北京站:ABT Forge + DID,Dap ...
- Asp.net MVC验证那些事(4)-- 自定义验证特性
在项目的实际使用中,MVC默认提供的Validation Attribute往往不够用,难以应付现实中复杂多变的验证需求.比如, 在注册用户的过程中,往往需要用户勾选"免责声明", ...
- 两步验证杀手锏:Java 接入 Google 身份验证器实战
转载自 两步验证杀手锏:Java 接入 Google 身份验证器实战 什么是两步验证? 大家应该对两步验证都熟悉吧?如苹果有自带的两步验证策略,防止用户账号密码被盗而锁定手机进行敲诈,这种例子屡见 ...
- 苹果再遭诉讼!因两步验证太过耗时...
限于iPhone XS系列新品的售价昂贵,创新度不足,苹果手机正在遭遇着前所未有的低迷状况,然而,即便硬件不给力,一般意义上来看,苹果在iOS系统上的优势还是存在的.但仍然有消费者不买账. 近期,名为 ...
- Asp.net MVC验证哪些事(2)-- 验证规则总结以及使用
上篇文章Asp.net MVC验证那些事(1)-- 介绍和验证规则使用中,介绍了Asp.net MVC中的验证功能以及如何使用.这里将对MVC中内置的验证规则进行总结. 一,查找所有验证规则 上篇文章 ...
- PHP设置谷歌验证器(Google Authenticator)实现操作二步验证
使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码.实现Google Authenticator功能需要服务 ...
- 三型两步验证登不上_苹果手机开启了双重认证,未信任的设备之前登入了,开启了双重认证未...
展开全部 首先需要明确的一个概念:「62616964757a686964616fe58685e5aeb931333365643661双重认证」不是「两步验证」. 「双重认证」与「两步验证」的区别 尽管 ...
- Python 使用 PyOTP 实现二步验证
二步验证 之前为服务器安装配置了 PVE 虚拟机系统,由于经常需要远程登陆以及通过 Web 进行管理,所以需要进一步提高安全性.PVE 提供了二步验证的功能,结合手机上的 FreeOTP 软件可以实现 ...
最新文章
- net项目总结一(1)
- 网络:HTTP报文格式
- 视频操作_02视频追踪:meanshift算法+Camshift算法
- java中equals的理解(1)
- mysql 服务已经存在_windows下mysql主从同步时从服务器出现表已经存在解决办法
- 搭建、使用与维护私有PyPi仓库
- 如何用深度学习 AI 美颜实现天天 P 图疯狂变脸算法? | 技术头条
- LXC与宿主机共享目录(七)
- 【算法】背包问题C++
- 归类常用控件GroupBox、TabControl、Expander
- 悟空遥控器 --- 手机投屏到电视 播放视频
- Python分析抖音数据,让视频爆起来
- 【电子产品】kindle使用心得.满满干货
- Turtlebot3 buger在仿真环境下建图导航
- 后端开发框架的具体内容是什么?
- 全景图的获取以及HTML页面显示全景图
- EXCEL去重统计(条件去重复计数)
- 2018秋季前端面试问题总结
- 咖说丨一文读懂中国区块链“链圈”发展现状
- LMD0 (ospid: 8664): terminating the instance due to error 481
热门文章
- Codeforces 488A Giga Tower(水)
- Python解决unicode编码 \xe7\xbb\x87转化为中文
- SQL练习:查询近30天活跃用户数
- 用你的左脑pk右脑,思维导图用哪个?
- at指令 meid_AT指令介绍及用法,AT 指令集合
- Level3_Unit1_Part3#Dialogue·Are Selfies Good or Bad?
- mysql 电子书_MySQL开发与实践 (付森等著) 中文pdf扫描版[45MB]
- Zstack 鼎阳SDS6204示波器和Archiver Appliance的重度测试1
- 关于mdm9206 threadx_os的I2c操作相关的API,
- 【DHT11读取负温度】