Java を使用してアクティベーション コードとキーを生成する方法。
復号化と暗号化の設計アイデア
暗号化:
AES 対称暗号化と復号化の使用
7 桁: 32 桁のシーケンス (4 桁) キー カテゴリ ( 2 桁) ) 有効期間 (1 桁)
暗号化キーは 11 桁です
4 桁: 最初の 3 桁は、まず乱数 (0 ~ 2500) を取得し、次に 11 を掛けて、A 3 に変換します。 -桁の 16 進数、最後の桁は (マシンのバージョン番号)、
最後の 3 桁と 1 桁で 4 桁の数値が生成されます
予期される 15 桁のキー
11 桁と 4 桁
その後、キーはスクランブルされて混乱します
混乱戦略: まずアクティベーション コードの奇数桁と偶数桁をそれぞれ取得し、次に奇数桁と偶数桁を結合して難読化されたアクティベーション コードを取得します
奇数桁と偶数桁
復号化:
(1) 難読化を解除します (難読化されたアクティベーション コードを再編成して復元します)
(2) キーの最後の 4 桁を確認します。成功しました。続行 ワンステップ操作。検証が失敗した場合、キーは無効です。
(3) 最初の 11 キーは、検証が成功した場合にのみ復号化できます。検証が失敗した場合、キーは無効です。
(4) ) 復号化が成功した場合は、それが有効なキーであることを示し、キー情報を取得し、その情報に基づいてクライアント上で対応する操作を実行します。復号化は失敗し、キーが無効であることを示します
(5)復号化が成功したかどうかを確認するには、サーバーにリクエストを送信し、サーバーに通知して、対応する操作と記録を実行します。
その中で、キー カテゴリ (2 桁) を使用して、どのデバイスまたはプラットフォームが復号化されているかを示すことができます。アクティベーション コードはアクティベーションに使用されます (たとえば、01 は特定のプラットフォームを表し、02 は特定のアプリを表します)。期間 (1 桁) アクティベーション コードの有効期間を示すために使用されます (たとえば、0 は永久、1 は 7 日間、2 は 7 日間を意味します) 30 日などを意味します)
注: 最初の 7 桁は 11 桁に暗号化され、アクティベーション コードを生成できる番号であることを示します。最後の 4 桁は乱数 * 11 ~ 32 の 10 進数と難読化です。戦略はアクティベーション コードを暗号化するためのもので、アクティベーション コードが有効かどうかを確認するために使用されます。
- 混乱戦略
- 32 16 進数への変換と 11
- AES で割り切れるかどうかは禁止です対称暗号化、復号化
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; } } }
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); } }
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);
}
}
ログイン後にコピー実行結果:
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 を使用してアクティベーション コードとキーを生成する方法。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

Java は、初心者と経験豊富な開発者の両方が学習できる人気のあるプログラミング言語です。このチュートリアルは基本的な概念から始まり、高度なトピックに進みます。 Java Development Kit をインストールしたら、簡単な「Hello, World!」プログラムを作成してプログラミングを練習できます。コードを理解したら、コマンド プロンプトを使用してプログラムをコンパイルして実行すると、コンソールに「Hello, World!」と出力されます。 Java の学習はプログラミングの旅の始まりであり、習熟が深まるにつれて、より複雑なアプリケーションを作成できるようになります。
