当前位置:

首页 > 编程开发 > 怎么使用java生成激活码和密钥

怎么使用java生成激活码和密钥

解密与加密设计思路加密:采用AES对称加密、解密7位数:32进制序列(4位)+密钥类别(2位)+有效时长(1位)加密后密钥为11位4位数:前三位,先获取一个(0到2500)的随机数,然后再乘11,接着转换为三位的32进制数,然后最后一位是(机器版本号),最后3位+1位生成4位数预想15位密钥11位+4位接着密钥打乱顺序混淆混淆策略:先分别获取激活码的奇数位和偶数位,然后将奇数位和偶数位拼接获得混淆后的激活码奇数位+偶数位解密:(1)解除混淆(将混淆后的激活码进行重组复原)(2)校验密钥后四位;校验成功继续

本文目录

    解密与加密设计思路

    加密:
    采用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生成激活码和密钥

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。