微信/支付宝的付款码,你知道怎么实现的吗?
付款码,你真的熟悉它吗?
付款码大家司空见惯了,每天都用,但是有多少人了解它呢? 平时新闻里面经常说不要把付款码泄露给别人,真的有那么危险吗?
其实,数学家和算法工程师才没那么笨,现在介绍几个算法,来探究一下付款码是怎么实现的。
付款码的交互流程
所谓的付款码,实际上是一串动态数字密码,由微信/支付宝生成,商户扫了付款码后,上传到微信/支付宝服务器,通过验证后,系统提取用户ID后即可完成扣费操作。
动态令牌算法
动态令牌算法叫做OTP(One-Time-Password,一次性密码),其中对于次数限制和时间限制,会有两种略有差别的算法:
- HOTP (HMAC-based One-Time Password),表示基于特定数值算法加密的一次性密码。
- TOTP (Time-based One-Time Password),表示基于时间戳算法的一次性密码。
TOTP实际上是HOTP的一种变种算法,只是将特定数值跟时间关联起来。
TOTP签名生成原理
首先,厂商一般会在软件内置两个参数:密钥K
和质数M
。
其中密钥K
是用来生成签名信息,质数M
是用来做用户ID分割。
HTOP的运算公式为:
//K为密钥字符串
//C为特定值,一般情况下为随机值
//Truncate函数是将截取加密后的串,并取加密后串的某些字段组成一个数字
HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
TOTP的运算公式为:
//T 表示当前Unix时间戳,单位秒
//一般T0 = 0
//X 表示时间步数,也就是说多长时间产生一个动态密码,这个时间间隔就是时间步数X,比如支付宝是60秒
//这个公式表达是从系统起始到现在,当前属于第几个密码周期
C = (T - T0) / X
//直接调用HOTP即可计算出来
TOTP(K,C) = HOTP(K,C)
不同厂家,X
参数会有不同:
- 阿里巴巴的身份宝使用的时间步数是60秒;
- 工商银行U盾令牌使用的时间步数是5分钟;
- Google的 身份验证器的时间步数是30秒;
- 腾讯的Token时间步数是60秒;
付款码生成
初中数学老师教过,由于质数
是的约数只有1和自己,所以通过简单的除法
和求余
就能轻松分离TOTP签名
和用户ID
。数学就是那么魔幻炫酷。
//质数M取值需要大于最大用户ID,如:当前系统设计最大承受用户有9990人,则质数可以设定必须大于9990
付款码=TOTP签名 * 质数M + 用户ID
付款码还原
TOTP签名 = 付款码 / 质数M
用户ID = 付款码 % 质数M
拿到用户ID
后,就可以查询数据库,取出用户的密钥K
,通过当前的时间周期进行同步签名验证TOTP签名
,如果签名通过,说明用户是在有效期内上传的付款码,接下来就是判断付款码是否使用过,没用过的话,就可以继续走风控和扣款流程了。
实际开发中,并不会将用户ID
放进来,而且改成密钥ID
,这样子同一个用户在不同设备上,就可以使用不同的密钥K
生成不一样的付款码了,也利于厂商追踪支付渠道。
总结
- 通过以上算法可以得知,
用户ID
和质数M
是公开的,只有密钥K
是必须保密的 - 微信、支付宝等都会使用加密和空间去存储这个
密钥K
,而且会定时同步更新服务器时间 - 银行U盾这种离线设备,就会将
密钥K
加密存到硬件内部 - 不必要担心截图付款码就会被人盗刷,毕竟付款码有效期只有短短的60秒