微信和支付宝离线付款码,动态密码保护器实现原理探索(2)
今天这篇文章主要讲微信和支付宝的离线付款码的一种实现思路。
付款码就是我们出示给商家扫码的一种码,这种码在首次初始化之后,不用联网也可以动态生成。
本文仅代表个人的一种实现原理的探索,仅供参考,不代表实际支付宝的付款码实现方案,也许支付宝的付款码实现方案算法更加完美,更加好。
如果有更好的算法和想法,欢迎评论和我探讨。
下面是摘自支付宝的付款码功能说明:
离线使用
首次使用时,需要网络才可以进行支付。之后无须网络也可以支付付款安全
二维码,条形码每分钟会自动更新,并会在生成之后短时间之内有效。
从首次使用,需要网络这一点可以看出,支付宝客户端肯定是向服务器请求了用来生成付款码的秘钥的。
下面是支付宝付款码的数字
2816 7565 2589 992104
微信付款码的数字
1345 7744 7121 375039
都是一样的格式,前面三个四位数的数字加上后面一个6位数的数字
再看看一下付款码的商家侧的流程,详细可以看微信支付的付款码文档
这里简单描述一下流程就是
扫码枪等商家的设备在获取到用户的付款码之后,把付款码发送到商户后台系统,商户后台系统再向微信支付系统发起支付请求,然后查询支付结果。
这里有一点需要注意的是:和上一篇文章讲的将军令的六位数的动态密码不一样的是,将军令是知道你的对应的用户信息的。但是商户后台在把付款码发送到微信支付请求支付的时候,商户后台是不知道这个付款码是哪个用户的。因为扫码设备,只是扫到了付款码的数字,然后就发送到商户后台了,是不可能追踪到时哪个用户的付款am的。所以可以肯定的是这18位的付款码数字是包含了用户信息的。
所以这里和上一篇文章的6位动态密码有很大区别,那就是这18位付款码数字需要携带用户的个人信息。
这样子的话,生成18位付款码需要的条件是:
- 每分钟随机生成
- 一旦截图或者退出后台,付款码需要重新生成
- 携带用户的信息
- 必须是18位数字
- 付款码是一次性使用的,使用过的不能重新使用
- 和设备绑定
- 生成后的付款码在一定时间内是有效的,也就是说假设有效期是20秒,那么为了安全,20秒前生成的付款码就报废了
所以如果要实现付款码的功能,那么需要满足上面的条件才可以。
付款码应该有两个部分,一个部分是需要解密的部分,另一个部分是纯哈希
解密部分就是需要获取到这个付款码是属于哪个用户的,纯哈希指的就是将用户设备的时间分钟级别,半分钟级别加上用户的设备识别码,用户的ip,用户的手机等信息,用户的地址,等等一系列信息做一个哈希。
然后服务器在根据解密的用户信息,在数据库里面查询用户的相关信息,同样做一个哈希,如果能匹配的话,就能证明是这个用户。
哈希这一点和上一篇文章一样很好理解,关键在于解密用户信息,同样要支持动态生成。
用户信息这个东西字段是很大的,像支付宝这种级别的应用,用户超过好几亿,就算使用简单的数字递增算法,讲过加密之后,加密的内容也是比原文多的。任何加密算法都是一样的,密文肯定是比原文的字节数要多的。否则的话,信息就要丢失,那就是哈希算法了,而不是加密算法。
假设用户的支付宝id是794850067,这里就有9位数了。9位数的话,意味着可以容纳大约10亿个id,放宽到10位数,那么支付宝就可以标记一个用户了。往前填充位数为0。
因此假设的支付宝id就是0794 8500 67 一共10位数。
接下来就是哈希信息,这个需要服务器和客户端使用相同的哈希算法和加密算法。
读者可以回到上一章节的信息,假设客户端和服务端计算得到的哈希码是676890,注意这个哈希码是和时间有关的。
假设当前时间是1561648680(秒级别),也就是10位数。
那么支付宝id加上时间组成前面十位数。当然支付宝肯定不会这么简单把前面十位数表示成时间戳加上支付宝id
这个时间戳生成肯定是有动态算法混淆的,比如当处于联网的时候,可能就把十位数再加上一个固定的数字,这个数字是保存到支付宝客户端的。
这样的话,支付宝id加上时间位数,最多不超过12位数用来表示身份信息。
然后剩下的6位数用来存放上一篇文章讲到的哈希密码。
这样支付宝在获取到付款码的时候,先解开前面的12位信息,获取到用户信息。再计算出对应的动态哈希,这样就可以验证成功了。
简单表述一下:
alipay_id = 794850067
unix_time_id = 1561648688
dynamic_id = 156677889 # 这个额外id是我自己的一种设计,假想支付宝服务器和客户端协商的,每天生成不同序列的id,同步
hash_id = 66777888 # 这个hash id是客户端计算用户各种信息做一个汇总得出的哈希
final_id = str(alipay_id+unix_time_id+dynamic_id) + str(hash_id)
print(len(final_id))
所以动态生成变化的就是unix_time_id ,dynamic_id,hash_id
因为前面12位数是alipay_id+unix_time_id+dynamic_id这几个相加的,所以是会动态变化的。
后面的hashid也是会变化的。
支付宝服务器收到付款码之后,可以用前面12位数减去动态id再减去时间id就可以得到用户id
然后再根据用户id计算hashid