JAVA生成序列号

news/2024/12/29 21:10:12/

一、生成序列号思路简述

使用非对称加密技术RSA实现

对RSA不了解的可先看上一篇:Java对称与非对称加密解密(AES与RSA)。

第一步:使用RSA生成一对密钥对;

第二步:将第一步生成的私钥保存至服务端,此私钥和客户端一一对象。公钥提供至客户端;

第三步:服务端使用第一步生成的私钥、客户端MAC地址、有效结束时间 三个信息生成序列号;

第四步:服务端将第三步生成的序列号提供至客户端;

第五步:客户端将序列号配置进系统;

第六步:访问客户端系统时,客户端使用公钥对序列号进行解释,解释出来的MAC地址和有效结束时间,之后使用解释出来的MAC地址和本机MAC地址做校验,将有效结束时间和当前时间做比较。当MAC地址和本机地址匹配并且有效结束时间大于当前时间时允许访问系统和访问资源,否则禁止访问并提示序列号过期。

二、maven依赖

        <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.5</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.directory.studio/org.apache.commons.codec --><dependency><groupId>org.apache.directory.studio</groupId><artifactId>org.apache.commons.codec</artifactId><version>1.8</version></dependency>

三、java代码

RSA加密工具类封装

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import org.apache.commons.codec.binary.Base64;
import java.security.KeyPair;public class RSAUtil {private String publicKey;private String privateKey;/*有参构造方法,加解密时使用。公钥加密需用私钥解密,私钥加密需用公钥解密*/public RSAUtil(String publicKey,String privateKey){this.publicKey = publicKey;this.privateKey = privateKey;}/*无参构造方法,新建密钥对时使用*/public RSAUtil(){KeyPair pair = SecureUtil.generateKeyPair("RSA");publicKey = new String(Base64.encodeBase64(pair.getPublic().getEncoded()));privateKey= new String(Base64.encodeBase64((pair.getPrivate().getEncoded())));}/**** @param str 加密前数据* @return 返回加密后数据*/public String encrypt(String str){return SecureUtil.rsa(privateKey,publicKey).encryptBcd(str, privateKey!=null?KeyType.PrivateKey:KeyType.PublicKey);}/**** @param str 加密后的数据* @return 返回解密后数据*/public String decrypt (String str){return SecureUtil.rsa(privateKey,publicKey).decryptStrFromBcd(str, privateKey!=null?KeyType.PrivateKey:KeyType.PublicKey);}public String getPublicKey() {return publicKey;}public String getPrivateKey() {return privateKey;}
}

序列号属性实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Serial {/*序列号解密时使用*/public Serial(String publicKey,String serialNumber){this.publicKey = publicKey;this.serialNumber = serialNumber;}/*序列号*/private String serialNumber;/*公钥*/private String publicKey;/*私钥*/private String privateKey;/*有结束时间(13位时间戳)*/private String effectiveEndTime;/*MAC地址*/private String mac;
}

序列号生成、解释工具类封装

package com.coolxiaoqi.springbootserialnumber.utils;import com.coolxiaoqi.springbootserialnumber.entity.Serial;public class SerialUtil {/*** 根据私钥、MAC地址、有效期生成序列号* @param serial 需有privateKey、mac、effectiveEndTime(13位时间戳)值* @return serial 含有privateKey、mac、effectiveEndTime、serialNumber值* @throws Exception*/public static Serial generateSerialNumber(Serial serial) {RSAUtil rsa = new RSAUtil(null,serial.getPrivateKey());String serialNumber = rsa.encrypt(serial.getMac()+","+serial.getEffectiveEndTime());serial.setSerialNumber(serialNumber);return serial;}/*** 根据序列号、公钥校验序列号是否有效* @param serial 需有publicKey、serialNumber* @return serial 含有publicKey、mac、effectiveEndTime、serialNumber值* @throws Exception*/public static Serial explainSerialNumber(Serial serial) {RSAUtil rsa = new RSAUtil(serial.getPublicKey(),null);String[] serialList = rsa.decrypt(serial.getSerialNumber()).split(",");serial.setMac(serialList[0]);serial.setEffectiveEndTime(serialList[1]);return serial;}
}

测试

import cn.hutool.core.net.NetUtil;
import com.coolxiaoqi.springbootserialnumber.entity.Serial;
import com.coolxiaoqi.springbootserialnumber.utils.RSAUtil;
import com.coolxiaoqi.springbootserialnumber.utils.SerialUtil;
import org.junit.jupiter.api.Test;import java.net.InetAddress;
import java.sql.Timestamp;public class SerialUtilTest {/*** 测试方法* 生成rsa密钥对,需保存密钥对,后边生成序列号和解释序列号需要用到*/@Testpublic void getKeyPairStart(){/*提前生成好rsa密钥对,私钥保存至服务端,公钥写入至客户端*/RSAUtil rsa = new RSAUtil();System.out.println("我是rsa公钥,请将我保存:"+rsa.getPublicKey());System.out.println("我是rsa私钥,请将我保存:"+rsa.getPrivateKey());}/*** 测试方法* 生成序列号,生成后将序列号提供至客户端进行配置*/@Testpublic void generateStart(){long currentTime = new Timestamp(System.currentTimeMillis()).getTime();/*new一个序列类,构造时传入私钥、MAC地址、有效结束时间*/// Serial serial = new Serial("MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ5+LRzIrPPKokLnmQu1Ncy/9efFtBHrV/PKQ59E0H0L1qmeFqm5snl7vRRW1LTiZp7C08U6+ZBmk/SEfk9WYVIromtBgJpAwj5tqNjwqg9g8z/X3Jr6YOVsxG9AUNShdYh++KLr33XZQIBQ5iA4ueOsU2NOUIn9dRCxcFUM2UsfAgMBAAECgYAZ+SuDcA+H1ElLFZErLgMnDr5JwUiFN0Aun5L9YtWX6HzBRzsHjXsGFZUi5CfvjLqsgdkalVOYqnbMt3nLnqhMAMjfzkT5cZK/gV9DZdKNL/KT60ZQlkzJL/b5dxs+3oYhkEB5klTARmjZzpu8a1wLNGU5ECHZRgqQXS5bhttpQQJBANnwSwO4akUfl8pMUg5L8520pv5WAjiY1ONAuSAUdvMBQ1BhcHKlMRQD/sgDS+qZpWb/dIJxvEorKBK+zY6Ff1kCQQC6LCcgZbQR2JcYF6t4fR531SYzkrVw5YnMKA0gOAdB1TvIC/NiSiEJSRYYJu2wOXLLkA93nJnV5xMN5UjSu4c3AkAiLA9XEf93vzBpw/XJ0Bbuz3ivwISwoyYeS/O7F/pet//6Bo0/LK+5V7cHXZz1uAm7UKrQGU1Qw9uQtOI+SqhhAkEAjniFhMRv9gxDLJvIjA9sBpZmgqcuFPSD7GlmChb2bsno0uFaYwiJmZqFvvvjf62nDOL1Azsjes84BLVHcoUyJwJBANmiKNmjVQ6ZS8MoCKutwNGfB+iNPKucb/yvmfT7vKMh1C0BbrZVI+5P5kYn5/DyuqhC8QrBMK0gK3DH+2pQUNo=","00-E0-4C-68-27-DE","1677592201000");Serial serial = new Serial("MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ5+LRzIrPPKokLnmQu1Ncy/9efFtBHrV/PKQ59E0H0L1qmeFqm5snl7vRRW1LTiZp7C08U6+ZBmk/SEfk9WYVIromtBgJpAwj5tqNjwqg9g8z/X3Jr6YOVsxG9AUNShdYh++KLr33XZQIBQ5iA4ueOsU2NOUIn9dRCxcFUM2UsfAgMBAAECgYAZ+SuDcA+H1ElLFZErLgMnDr5JwUiFN0Aun5L9YtWX6HzBRzsHjXsGFZUi5CfvjLqsgdkalVOYqnbMt3nLnqhMAMjfzkT5cZK/gV9DZdKNL/KT60ZQlkzJL/b5dxs+3oYhkEB5klTARmjZzpu8a1wLNGU5ECHZRgqQXS5bhttpQQJBANnwSwO4akUfl8pMUg5L8520pv5WAjiY1ONAuSAUdvMBQ1BhcHKlMRQD/sgDS+qZpWb/dIJxvEorKBK+zY6Ff1kCQQC6LCcgZbQR2JcYF6t4fR531SYzkrVw5YnMKA0gOAdB1TvIC/NiSiEJSRYYJu2wOXLLkA93nJnV5xMN5UjSu4c3AkAiLA9XEf93vzBpw/XJ0Bbuz3ivwISwoyYeS/O7F/pet//6Bo0/LK+5V7cHXZz1uAm7UKrQGU1Qw9uQtOI+SqhhAkEAjniFhMRv9gxDLJvIjA9sBpZmgqcuFPSD7GlmChb2bsno0uFaYwiJmZqFvvvjf62nDOL1Azsjes84BLVHcoUyJwJBANmiKNmjVQ6ZS8MoCKutwNGfB+iNPKucb/yvmfT7vKMh1C0BbrZVI+5P5kYn5/DyuqhC8QrBMK0gK3DH+2pQUNo=","00-E0-4C-68-27-DE",(currentTime+1000*30)+"");/*生成序列号,参数是引用类型,调用生成序列号方法后可直接从对象中获取序列号*/SerialUtil.generateSerialNumber(serial);/*获取序列号*/String serialNumber = serial.getSerialNumber();System.out.println("我是生成的序列号,请发送至客户端:"+serialNumber);}/*** 测试方法* 校验序列号是否有效*/@Testpublic void explainStart(){try {/*new一个序列类,构造时传入公钥、序列号*/Serial serial = new Serial("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCefi0cyKzzyqJC55kLtTXMv/XnxbQR61fzykOfRNB9C9apnhapubJ5e70UVtS04maewtPFOvmQZpP0hH5PVmFSK6JrQYCaQMI+bajY8KoPYPM/19ya+mDlbMRvQFDUoXWIfvii69912UCAUOYgOLnjrFNjTlCJ/XUQsXBVDNlLHwIDAQAB","3231551E45B23CEE6D66546EFAFB8F6E487A4ED1377AD568C82346B94639D707122EEE1E7F9978EBFA9E7213A59B22AD0AF2AA367FBBD564617E45AC9FB9A4EB19A7E40B2AD81611ED2FDE0C347F99166B79603B21C64CCBD8C371DD3026FE7E39BF19159B4B425D22061AA462B882DA44DC542CAD56CCD1C851DFEDBA75BB7D");/*解释序列号,参数是引用类型,调用解释序列号方法后可直接从对象中获取MAC地址、有效结束时间*/SerialUtil.explainSerialNumber(serial);/*获取MAC地址*/String mac = serial.getMac();/*获取有效结束时间*/String effectiveEndTime = serial.getEffectiveEndTime();/*获取本机MAC地址*/// String localMac = LocalMac.getLocalMac(InetAddress.getLocalHost());InetAddress localHost = InetAddress.getLocalHost();String macAddress = NetUtil.getMacAddress(localHost);/*获取当前时间戳*/long time = new Timestamp(System.currentTimeMillis()).getTime();/*判断有效结束时间是否大于当前时间*/System.out.println("解析过后的Mac地址:"+mac);System.out.println("客户端的Mac地址:"+macAddress);// System.out.println(mac.equalsIgnoreCase(macAddress));System.out.println("解析出的过期时间戳:"+effectiveEndTime);System.out.println("当前时间戳:"+time);// System.out.println(Long.parseLong(effectiveEndTime)>time);if(mac.equalsIgnoreCase(macAddress)&&Long.parseLong(effectiveEndTime)>time){System.out.println("当前序列号有效,可正常使用系统与访问资源");}else{System.out.println("当前序列号无效,请向厂商购买新的序列号");}} catch (Exception e) {e.printStackTrace();}}
}


http://www.ppmy.cn/news/361158.html

相关文章

M1芯片CAD如何安装?M1 mac怎么安装AutoCAD?

最近许多朋友问M1的Mac是不是可以安装AutoCAD&#xff0c;小编很负责任的告诉大家&#xff0c;AutoCAD目前来说只支持Intel Mac&#xff01;&#xff01;&#xff01;这时肯定就有朋友就好奇了&#xff0c;那你为什么标题还写M1 mac怎么安装AutoCAD&#xff1f; M1 Mac早在CAD2…

CorelDRAW2021标准版 序列号授权码

作为一个设计师没有CorelDRAW用的日子真的是难过&#xff0c;最好用的就是CorelDRAW 2021的增强中文版&#xff0c;拥有极强的插件&#xff0c;为作图方便了不少&#xff01;CorelDRAW作为世界一流的平面矢量绘图软件&#xff0c;被专业设计人员广泛使用&#xff0c;软件使用直…

CAD2007学习笔记

先说说各个版本CAD激活的问题&#xff0c;在软件管家下载的安装包一般附带注册机&#xff0c;安装好后输入统一序列号&#xff1a;666-69696969 软后输入对应版本的密钥&#xff1a;2010版密钥001B1 2011版密钥001C1 2012版密钥001D1 2013版密钥001E1 2014版密钥001F1…

入门编程其实也简单

随着信息技术的快速发展&#xff0c;编程已经成为一个越来越重要的技能。那么&#xff0c;我们该如何入门编程呢&#xff1f; 编程是指使用计算机语言编写计算机程序的过程。计算机程序是一系列指令的集合&#xff0c;这些指令告诉计算机要执行的操作。编程的目的是创建计算机…

《大卫科波菲尔》社会网络分析

《大卫科波菲尔》社会网络分析 1.简介1.1数据集介绍1.2社会网络分析简介1.3《大卫科波菲尔》介绍 2.描述性统计3.网络概述4.社区发现5.好句摘抄6.总结和不足 1.简介 1.1数据集介绍 Newman教授的个人数据网站 网址&#xff1a;http://www-personal.umich.edu/~mejn/netdata/ 从…

百度关键词模拟点击破解版 SEO排名优化神器

百度关键词模拟点击破解版 SEO排名优化神器 软件用于&#xff1a;关键词模拟点击软件、排名作弊优化、百度关键词点击软件、百度关键词点击 接触SEO优化的朋友应该了解这软件&#xff0c;网上也有一些需要付费的&#xff0c;我也用过&#xff0c;效果不敢说特别好。 不过搜索…

<Linux开发>驱动开发 -之-内核定时器与中断

&#xff1c;Linux开发&#xff1e;驱动开发 -之-内核定时器与中断 交叉编译环境搭建&#xff1a; &#xff1c;Linux开发&#xff1e; linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下&#xff1a; &#xff1c;Linux开发&#xff1e; -之-系统移植 uboot移植过程详…

分享推荐冰箱压缩机主控方案MM32SPIN0230

压缩机是一种将低压气体提升为高压气体的从动的流体机械&#xff0c;是制冷系统的心脏。它从吸气管吸入低温低压的制冷剂气体&#xff0c;通过电机运转带动活塞对其进行压缩后&#xff0c;向排气管排出高温高压的制冷剂气体&#xff0c;为制冷循环提供动力。 RAMSUN以MM32SPIN…