您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么使用java生成激活碼和密鑰”,在日常操作中,相信很多人在怎么使用java生成激活碼和密鑰問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么使用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生成激活碼和密鑰”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。