base32编码指的是基于32个可打印字符对任意字节数据进行编码:大写字母A-Z以及数字2-7。
兑换码要求:长度为10个字符
如果将这32个字符依次放到一个base数组中,那么最大的下标就是31。我们将要编码的任意字节数据按照五个bit为一组进行划分,那么最大值就为11111--》31,最小值00000--》0。刚好就对应base数组中的最大和最小下标,根据下标去查找对应的32个可打印字符,得到结果。
比如:我们对319290478070746进行Base32,转成二进制
01001000100110010010011011100001101000101111011010
然后5个bit一组:
01001 00010 01100 10010 01101 11000 01101 00010 11110 11010
每组转成一个十进制下标去base数组中取值,可以得到KCNUP2PM84。
此时通过base32编码后得到的兑换码是不安全的,因为通过base32解码它是可逆的,比较简单。
优惠劵兑换码一般要求:
保证兑换码的唯一性,兑换码不能被重复使用
不能轻易的被人爆刷。
生成以及验证效率要满足。
(UUID和雪花可以实现吗?)
兑换码算法优化:
兑换码分为明文以及密文;
明文就是50个bit数据,密文就是结果base32编码后的字符串。
明文计算:
把50个bit分为3段结构:14位签名+4位新鲜值+32位序列号(签名+载荷)
序列号:可以通过redis自增来进行生成:如1001
新鲜值:可以是优惠劵id的后4个bit,主要用来从一个自定义的密钥表获取密钥。
载荷:将新鲜值与序列号进行拼接得到。
签名:将得到的载荷4个bit一组乘以自定义的权重表中,进行累加后取后14个bit作为签名
最后将3段拼接进行base32编码得到兑换码。
密文解码:
通过base32解码后得到50个bit,再根据以上的相关步骤倒推验证。