您好,欢迎访问一九零五行业门户网

如何利用Java生成激活码和密钥

解密与加密设计思路加密:
采用aes对称加密、解密
7位数: 32进制序列(4位) + 密钥类别(2位)+ 有效时长(1位)
加密后密钥为11位
4位数:前三位,先获取一个(0到2500)的随机数,然后再乘11,接着转换为三位的32进制数,然后最后一位是(机器版本号),
最后 3位+1位 生成4位数
预想15位密钥
11位+4位
接着密钥打乱顺序混淆
混淆策略:先分别获取激活码的奇数位和偶数位,然后将奇数位和偶数位拼接获得混淆后的激活码
奇数位+偶数位
解密:
(1) 解除混淆(将混淆后的激活码进行重组复原)
(2) 校验密钥后四位;校验成功继续下一步操作,校验失败密钥无效
(3) 只有校验成功才能对前十一位密钥进行解密;校验失败密钥无效
(4) 解密成功,说明是有效密钥,获取密钥信息,根据信息对客户端进行相应操作;解密失败,说明密钥无效
(5) 无论解密成功与否给服务端发请求,通知服务端,然后进行相应的操作和记录
其中:密钥类别(2位)可以用来表示该激活码用来激活哪些设备或者哪些平台(如01表示某个平台,02表示某个app),时长(1位)用来表示该激活码的有效时长(如0表示永久、1表示7天、2表示30天等)
注意:前7位数加密后为11位,表示该激活码可以生成的个数;后4位数为随机数 * 11转32进制和混淆策略是为了激活码的加密性,用来校验该激活码是否有效
因此,该激活码的加密主要体现在三个地方:
混淆策略
32禁止转18进制后能否被11整除
aes对称加密、解密
解密与加密工具类cdkeyutil.java
import java.util.random;/** * created by tao. * date: 2021/6/28 16:43 * 描述: */public class cdkeyutil { //机器版本号 /** * 激活码生成方法 * * @param category 密钥类别(固定两位数字) * @param deadline 使用期限(固定一位字符) * @return 返回的激活码 */ public static string createcdkey(string category, string deadline, string machineversion) throws exception { string cdkey = ""; //1. 获取前四位 string sequence = getsequence(); //2. 生成前七位 string plaintext = sequence + category + deadline; //3.对明文进行加密 cdkey = cdkeyencryptutils.aesencrypt(plaintext).substring(0, 11); //4.获取后四位 string rulessequence = cdkeyutil.getrulessequence(machineversion); //5.混淆操作 cdkey = cdkey + rulessequence; cdkey = confusion(cdkey); //6.得到激活码 return cdkey; } /** * 激活码解码方法 * * @param cdkey 激活码 * @return 返回激活码明文 */ public static string decdkey(string cdkey, string machineversion) throws exception { //1. 解除混淆 string deconfusion = deconfusion(cdkey); //2. 提取后四位序列(第1位版本号,后三位校验其规则) string sequence = deconfusion.substring(deconfusion.length() - 4); //3. 获取后三位序列并且转为10进制,和版本号 string randomint = sequence.substring(1); string version = sequence.substring(0, 1); int to10 = integer.parseint(change32to10(randomint)); //4. 根据既定规则校验激活码是否正确 if (to10 % 11 == 0 && version.equals(machineversion)) { //1. 如果后四位序列校验正确,则对激活码进行解密操作 string secretkey = deconfusion.substring(0, 11); string code = ""; try { code = cdkeyencryptutils.aesdecrypt(secretkey); } catch (exception e) { e.printstacktrace(); return "激活码错误"; } return code; } else { return "激活码错误"; } } /** * 获得激活码前四位序列方法 * * @return 返回激活码前四位序列 */ public static string getsequence() { string sequence = ""; //1. 获取随机数 int randomint = getrandomint(); //2. 转32进制 string to32 = change10to32(randomint + ""); //3. 补全四位 int len = to32.length(); if (len < 4) { for (int i = 0; i < 4 - len; i++) { to32 = "0" + to32; } } sequence = to32; return sequence; } /** * 获得激活码后四位规则序列方法 * * @param machineversion 机器版本号 * @return 返回激活码后四位规则序列 */ public static string getrulessequence(string machineversion) { string rulessequence; //1. 按照规则获取前三位 /*int randomint = new random().nextint(8); string randomstr = randomint + "" + (randomint + 1) + (randomint + 2);*/ //1. 按照规则获取前三位 int randomint = new random().nextint(2500); string randomstr = (randomint * 11) + ""; //2. 转32进制 string to32 = change10to32(randomstr); //3. 补全三位 int len = to32.length(); if (len < 3) { for (int i = 0; i < 3 - len; i++) { to32 = "0" + to32; } } //4.拼接第四位 rulessequence = machineversion + to32; return rulessequence; } /** * 激活码混淆方法 * 奇数位+偶数位 * * @return 返回激活码混淆后的序列 */ public static string confusion(string cdkey) { string decdkey = ""; //1.获取奇数位字串 string odd = ""; for (int i = 0; i < cdkey.length(); i = i + 2) { odd = odd + cdkey.charat(i); } //2.获取偶数位字串 string even = ""; for (int i = 1; i < cdkey.length(); i = i + 2) { even = even + cdkey.charat(i); } //3.拼接 decdkey = odd + even; return decdkey; } /** * 激活码解除混淆方法 * * @return 返回激活码解除混淆后的序列 */ public static string deconfusion(string decdkey) { string cdkey = ""; //1. 拆分 int oddcount = (decdkey.length() / 2) + (decdkey.length() % 2); string odd = decdkey.substring(0, oddcount); string even = decdkey.substring(oddcount); //2. 复原激活码 if (odd.length() == even.length()) { for (int i = 0; i < odd.length(); i++) { cdkey = cdkey + odd.charat(i) + even.charat(i); } } else { for (int i = 0; i < even.length(); i++) { cdkey = cdkey + odd.charat(i) + even.charat(i); } cdkey = cdkey + odd.charat(odd.length() - 1); } return cdkey; } /** * 10进制转32进制的方法 * num 要转换的数 from源数的进制 to要转换成的进制 * * @param num 10进制(字符串) * @return 转换结果的32进制字符串 */ public static string change10to32(string num) { int from = 10; int to = 32; return new java.math.biginteger(num, from).tostring(to); } /** * 32进制转10进制的方法 * num 要转换的数 from源数的进制 to要转换成的进制 * * @param num 10进制(字符串) * @return 转换结果的10进制字符串 */ public static string change32to10(string num) { int f = 32; int t = 10; return new java.math.biginteger(num, f).tostring(t); } /** * 生成[min, max]之间的随机整数 * min 最小整数(固定0) * max 最大整数(固定1000000) * * @return 返回min———max之间的随机数 * @author tao */ public static int getrandomint() { int min = 0; int max = 1000000; return new random().nextint(max) % (max - min + 1) + min; } /* * 枚举日期,返回天数 */ public static int duetimeenum(string code) { switch (code) { case "0": return 36500; case "1": return 7; case "2": return 30; case "3": return 90; case "4": return 180; case "5": return 365; default: return 30; } }}
其中用到aes加密和解密:cdkeyencryptutils.java
import org.apache.commons.codec.binary.base64;import javax.crypto.cipher;import javax.crypto.spec.ivparameterspec;import javax.crypto.spec.secretkeyspec;/** * created by tao. * date: 2021/6/28 16:37 * 描述: */public class cdkeyencryptutils { //--------------aes--------------- private static final string key = "12055296"; // 密匙,必须16位 private static final string offset = "12055296"; // 偏移量 private static final string encoding = "utf-8"; // 编码 private static final string algorithm = "des"; //算法 private static final string cipher_algorithm = "des/cbc/pkcs5padding"; // 默认的加密算法,cbc模式 public static string aesencrypt(string data) throws exception { //指定算法、获取cipher对象(des/cbc/pkcs5padding:算法为,工作模式,填充模式) cipher cipher = cipher.getinstance(cipher_algorithm); //根据自定义的加密密匙和算法模式初始化密钥规范 secretkeyspec skeyspec = new secretkeyspec(key.getbytes("ascii"), algorithm); //cbc模式偏移量iv ivparameterspec iv = new ivparameterspec(offset.getbytes()); //初始化加密模式 cipher.init(cipher.encrypt_mode, skeyspec, iv); //单部分加密结束,重置cipher byte[] encrypted = cipher.dofinal(data.getbytes(encoding)); //加密后再使用base64做转码 return new base64().encodetostring(encrypted); } /** * aes解密 * * @param data * @return string * @author tao * @date 2021-6-15 16:46:07 */ public static string aesdecrypt(string data) throws exception { //指定算法、获取cipher对象(des/cbc/pkcs5padding:算法为,工作模式,填充模式) cipher cipher = cipher.getinstance(cipher_algorithm); //根据自定义的加密密匙和算法模式初始化密钥规范 secretkeyspec skeyspec = new secretkeyspec(key.getbytes("ascii"), algorithm); //cbc模式偏移量iv ivparameterspec iv = new ivparameterspec(offset.getbytes()); //初始化解密模式 cipher.init(cipher.decrypt_mode, skeyspec, iv); //先用base64解码 byte[] buffer = new base64().decode(data); //单部分加密结束,重置cipher byte[] encrypted = cipher.dofinal(buffer); return new string(encrypted, encoding); }}
其中aes的key为12055296,设置为8位,则机密后的密文则为11位,加密算法为 “des”
激活码生成测试 public static void main(string[] args) throws exception { for (int i = 0; i < 10; i++) { string cdkey = cdkeyutil.createcdkey("01", "0", "1"); system.out.println("激活码:" + cdkey); string decdkey = cdkeyutil.decdkey(cdkey, "1"); system.out.println("激活码解密:" + decdkey); } }
执行结果:
以上就是如何利用java生成激活码和密钥。的详细内容。
其它类似信息

推荐信息