使用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;
public class CDKeyUtil {
//机器版本号
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;
}
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 "激活码错误";
}
}
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;
}
public static String getRulesSequence(String machineVersion) {
String rulesSequence;
//1. 按照规则获取前三位
//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;
}
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;
}
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;
}
public static String change10To32(String num) {
int from = 10;
int to = 32;
return new java.math.BigInteger(num, from).toString(to);
}
public static String change32To10(String num) {
int f = 32;
int t = 10;
return new java.math.BigInteger(num, f).toString(t);
}
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;
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);
}
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生成激活码和密钥的方法的文章就介绍到这了,更多相关java生成激活码和密钥内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341