按关键词阅读:
original_secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsecret=BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))
「这个密钥客户端与服务端将会同时保存一份 , 两端将会同样的算法计算 , 以此用来比较动态码的正确性 。 」
我们以客户端为例 , 生成一个动态码 , 首先我们需要经过一个签名函数 , 这里 **Google Authenticator **采用的 「HMAC-SHA1」 , 这是一种基于哈希的消息验证码 , 可以用比较安全的单向哈希函数(如 SHA1)来产生签名 。
签名函数伪码如下:
hmac=SHA1(secret+SHA1(secret+input))
上面函数中的 , input 使用当前时间整除 30 的值 。
input=CURRENT_UNIX_TIME()/30
这里时间就充当一个动态变参 , 这样可以源源不断产生动态码 。
「另外这里整除 30 , 是为了赋予验证码一个 30 秒的有效期 。 」
这样对于用户输入来讲 , 可以有充足时间准备输入这个动态码 , 另外一点客户端与服务端可能存在时间偏差 , 30 秒的间隔可以很大概率的屏蔽这种差异 。
画外音:这个有效时间其实很考量 , 如果比较长 , 安全性就差 。
如果比较短 , 用户体验就很差 , 不容易输入准备 。
经过 「HMAC-SHA1」 签名函数以后 , 我们得到一个长度为 40 的字符串 , 我们还需要将其转化为 6 位数字 , 方便用户输入 。
处理的伪码如下:
four_bytes=hmac[LAST_BYTE(hmac):LAST_BYTE(hmac)+4]large_integer=INT(four_bytes)small_integer=large_integer%1,000,000
完整的算法伪码如下:
original_secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsecret=BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))input=CURRENT_UNIX_TIME()/30hmac=SHA1(secret+SHA1(secret+input))four_bytes=hmac[LAST_BYTE(hmac):LAST_BYTE(hmac)+4]large_integer=INT(four_bytes)small_integer=large_integer%1,000,000
当客户端将动态码上传给服务端 , 服务端查询数据库获取到用户对应的密钥 , 然后使用同样的算法进行处理生成一个动态码 , 最后比较客户端上传动态码与服务端生成是否一致 。
2. 付款码离线方案
上面我们了解了动态口令的实现方案 , 付款码生成原理其实也大致如此 。
不过付款码离线方案采用动态密钥的方式(全局唯一) , 定时请求服务端更换密钥 , 以此保证更高的安全性 。
另外在一次性动态口令方案 , 需要双方基于同样的秘钥 , 所以服务端需要明确知道这「背后正确用户」 。 以上面的登录场景为例 , 登录过程输入用户名,服务端就可以根据这个在数据库中查询相应的密钥 。
但是在付款码的支付场景中 , 支付过程仅仅传递一个付款码 , 就可以向相应的用户扣款 。 不用想 , 这个付款码这串数字一定包含相应的用户信息 。
所以付款码的相应的算法相比动态码会更加复杂 , 这样才可以有效保证安全性 。
看到这里 , 不知道你们是否急切想了解这套算法那?
这种算法岂能是我们能掌握的?
支付宝核心算法咱不知道 , 但是我们可以从其他人公开设计方案了解一个皮毛 。
这里小黑哥给你一个知乎网友@反方向的钟 回答的离线二维码实现方式 , 给你 look look:
本文图片
来自:https://www.zhihu.com/question/49811134/answer/135886638
3. 付款码离线码的劣势
最后我们来看下付款码离线方案的劣势:
第一 , 算法调整不灵活 , 如果相关算法较大的调整 , 可能需要升级客户端,并且这个期间服务端还需要兼容新老算法产生的付款码 。
第二 , 安全性问题 , 正常的情况相关密钥无法被普通用户获取 , 但是架不住有有心之人 。 他们可能通过获取手机用户 Root 权限或者越狱手机 , 利用恶意程序获取密钥 , 然后随意生成付款码 。
稿源:(人人都是产品经理)
【】网址:http://www.shadafang.com/c/hn0912921H42020.html
标题:authenticator|手机没网了,却还能支付,这是什么原理?( 三 )