大量兑换码的生成与验证方案(Java)

您所在的位置:网站首页 我的世界激活码十位数是什么意思 大量兑换码的生成与验证方案(Java)

大量兑换码的生成与验证方案(Java)

2023-12-04 11:32| 来源: 网络整理| 查看: 265

由于以前也做过很多兑换码的功能,但是也没有考虑过大量的兑换码的情况,所以这里尝试实现了一个生成与兑换的方案,分享出来。当然这不一定是最好的解决方案,这里仅供大家参考。有什么问题或可以优化的地方欢迎留言讨论。

*此方案可以根据输入的兑换码数量以及兑换码的字符长度来生成兑换码,每次生成兑换码的最大数量为int的最大值,一般为2147483647,即21亿个。

*此方案不需要数据库存储已生成的兑换码,直接使用验证算法即可验证兑换码是否有效。

*注意此算法的最短兑换码长度为12。这里可以根据需求对兑换码的结构进行调整来减少此长度。

首先说下思路

每一位兑换码有4部分构成:

[类型(1),id(4),随机码(n),校验码(1)]

类型为每次生成兑换码的组id,这里只用了1个byte来存储,可以根据需要增加。

id为每次生成的每个兑换码的唯一id。

随机码为每个兑换码的随机数。

校验码用来在验证兑换码时进行校验。

生成过程:

1.根据输入的兑换码总长度计算出随机码的位数,然后对每一位随机赋值。

2.把类型,id和随机码组成一个byte数组,计算总和,然后对byte.max进行取余运算,结果最为校验码。把校验码放在数组最末尾。

3.因为前面的时间和id有一定的规律性,我们使用随机码对时间和id进行异或操作,使兑换码看起来没有规律。

4.为了更加安全,我们使用一个密码对全部数据按顺序进行异或运算,这样即使知道了算法,在不知道密码的情况些也很难对数据进行破解。

5.我们使用32位的编码表来表示二进制数据,但是每个byte位长度为8,能表示127个数据,所以这里我们要对原数据进行拆分,32位编码表只需要5位就能表示,所以这里我们把原byte数组拆分为每5位为一个byte。如图:

红色部分直接补0,末尾不足的部分也补充为0.这样一位数据就可以正好对应编码表中的一个数据。

6.把我们重新整理好的byte数组按照编码表转换位字符串就是我们最终的兑换码。

验证的过程就是把生成的过程反过来执行一遍。

下面给出完整代码:

public class Redeem { static String stringtable = "abcdefghijkmnpqrstuvwxyz23456789"; final static String password = "dak3le2"; //从byte转为字符表索引所需要的位数 final static int convertByteCount = 5; public static void main( String[] args ) throws Exception { ShowTime(); System.out.println("======================="); create((byte)1,10000,12,password); VerifyCode("c8dksqjamaba"); VerifyCode("4a36g5npamna"); VerifyCode("4a36g5naamna"); VerifyCode("dafe33234g435"); VerifyCode("ga8ehxsq6dja"); } /** * 生成兑换码 * 这里每一次生成兑换码的最大数量为int的最大值即2147483647 * @param time * @param id * @param count * @return */ public static byte[] create(byte groupid,int codecount,int codelength,String password) { //8位的数据总长度 int fullcodelength = codelength * convertByteCount / 8; //随机码对时间和id同时做异或处理 //类型1,id4,随机码n,校验码1 int randcount = fullcodelength - 6;//随机码有多少个 //如果随机码小于0 不生成 if(randcount 48) & 0xFF), (byte) ((val >> 40) & 0xFF), (byte) ((val >> 32) & 0xFF), (byte) ((val >> 24) & 0xFF), (byte) ((val >> 16) & 0xFF), (byte) ((val >> 8) & 0xFF), (byte) (val & 0xFF) }; return arr; } public static byte[] Number2byte(int val) { byte[] arr = new byte[]{ (byte) ((val >> 24) & 0xFF), (byte) ((val >> 16) & 0xFF), (byte) ((val >> 8) & 0xFF), (byte) (val & 0xFF) }; return arr; } public static byte[] Number2byte(short val) { byte[] arr = new byte[]{ (byte) ((val >> 8) & 0xFF), (byte) (val & 0xFF) }; return arr; } }

运行Redeem类可以看到如下输出:

可以看到正确的码都可以验证成功,我们对原来的码做稍微的修改和随便输入的乱码都会验证失败。

这里在生成兑换码时,最后一步对原byte数组进行拆分操作,是生成一个新数组,然后根据原数组计算新数组中每一位的值,这里如果是在c/c++中会方便很多,直接只用指针访问地址,然后每5位操作一下就可以,但是在java暂时只能想到这种笨方法,不知道有没有更方便的方法,如果有,还请多多指教~~



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3