diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..5039140 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,67 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master ] + schedule: + - cron: '19 22 * * 0' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.gitignore b/.gitignore index 26498aa..143ba4a 100644 --- a/.gitignore +++ b/.gitignore @@ -41,5 +41,4 @@ hs_err_pid* .idea/ target/ *.iml -logs/ -.gitignore \ No newline at end of file +logs/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9031f2a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: java + +java: + - 1.8 + +sudo: false + +install: + - mvn clean install \ No newline at end of file diff --git a/LICENSE b/LICENSE index 257fa5c..ce3f3d8 100644 --- a/LICENSE +++ b/LICENSE @@ -176,7 +176,7 @@ recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2017 siter + Copyright 2018 SeanDragon Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index b1862f8..b6167b8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,70 @@ -# pro.tools:protools:2.0 +# protools -# future -1 在面向对象思想上思考更多,多线程场景深入思考 \ No newline at end of file +[](https://travis-ci.org/SeanDragon/protools) +[](https://github.com/SeanDragon/protools/blob/master/LICENSE) +[](#protools) + +[](https://github.com/SeanDragon/protools/fork) +[](https://github.com/SeanDragon/protools/watchers) + +
![]() |
+ ![]() |
+ ![]() |
+
![]() |
+ ![]() |
+ |
![]() |
+ ![]() |
+ ![]() |
+
* 此方法返回零位的最高位(“最左侧”)前在指定的int值的二进制补码表示法,或32个1位的数量,如果该值为零。
*
- * @param i 数字
+ * @param i
+ * 数字
+ *
* @return 结果
*/
public static int numberOfLeadingZeros(long i) {
@@ -134,7 +140,9 @@ public static int numberOfLeadingZeros(long i) {
/**
* 设置给DecimalFormat用的精度字符创
*
- * @param scale 精度
+ * @param scale
+ * 精度
+ *
* @return 结果
*/
public static String scale2FormatStr(int scale) {
@@ -174,6 +182,7 @@ public static DecimalFormat scale2Format(final int scale, final RoundingMode rou
/**
* @param value
* @param scale
+ *
* @return
*/
public static String number2Str(Double value, int scale) {
@@ -183,6 +192,7 @@ public static String number2Str(Double value, int scale) {
/**
* @param value
* @param scale
+ *
* @return
*/
public static Double number2double(Double value, int scale) {
diff --git a/common/src/main/java/pro/tools/data/image/ToolBarCode.java b/common/src/main/java/pro/tools/data/image/ToolBarCode.java
index 872f6ba..a77ad3b 100644
--- a/common/src/main/java/pro/tools/data/image/ToolBarCode.java
+++ b/common/src/main/java/pro/tools/data/image/ToolBarCode.java
@@ -1,19 +1,12 @@
package pro.tools.data.image;
-import com.google.zxing.BarcodeFormat;
-import com.google.zxing.BinaryBitmap;
-import com.google.zxing.EncodeHintType;
-import com.google.zxing.LuminanceSource;
-import com.google.zxing.MultiFormatReader;
-import com.google.zxing.MultiFormatWriter;
-import com.google.zxing.NotFoundException;
-import com.google.zxing.Result;
-import com.google.zxing.WriterException;
+import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import pro.tools.constant.StrConst;
@@ -22,8 +15,14 @@
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.file.Paths;
import java.util.Hashtable;
+import static com.google.zxing.BarcodeFormat.QR_CODE;
+
/**
* 条码处理
*
@@ -32,7 +31,7 @@
public final class ToolBarCode {
private ToolBarCode() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
@@ -45,16 +44,19 @@ private ToolBarCode() {
* @param savePath 保存路径
*/
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
- @Deprecated
public static void encode(String content, int width, int height, String fileType, String savePath) throws IOException, WriterException {
- content = new String(content.getBytes(StrConst.DEFAULT_CHARSET_NAME), StrConst.DEFAULT_CHARSET_NAME);// 二维码内容
- Hashtable hints = new Hashtable();
- hints.put(EncodeHintType.CHARACTER_SET, StrConst.DEFAULT_CHARSET_NAME);
- BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
- File file = new File(savePath);
- MatrixToImageWriter.writeToFile(bitMatrix, fileType, file);
+ Charset charset = Charset.forName("UTF-8");
+ CharsetEncoder encoder = charset.newEncoder();
+
+ byte[] b = encoder.encode(CharBuffer.wrap(content)).array();
+ String data = new String(b, "iso8859-1");
+
+ Writer writer = new QRCodeWriter();
+ BitMatrix matrix = writer.encode(data, QR_CODE, width, height);
+ MatrixToImageWriter.writeToPath(matrix, fileType, Paths.get(savePath));
}
+
/**
* 生成带logo的二维码
*
@@ -65,10 +67,22 @@ public static void encode(String content, int width, int height, String fileType
* @param fileType 文件类型,如png
* @param savePath 保存路径
*/
- public static void encodeLogo(String content, int width, int height, String logoPath, String fileType, String savePath) throws IOException {
- BitMatrix matrix = MatrixToImageWriterEx.createQRCode(content, width, height);
- MatrixToLogoImageConfig logoConfig = new MatrixToLogoImageConfig(Color.BLUE, 4);
+ public static void encodeLogo(String content, int width, int height, String logoPath, String fileType, String savePath) throws IOException, WriterException {
+ Charset charset = Charset.forName("UTF-8");
+ CharsetEncoder encoder = charset.newEncoder();
+
+ byte[] b = encoder.encode(CharBuffer.wrap(content)).array();
+ String data = new String(b, "iso8859-1");
+
+ Writer writer = new QRCodeWriter();
+ BitMatrix matrix = writer.encode(data, QR_CODE, width, height);
+ MatrixToLogoImageConfig logoConfig = new MatrixToLogoImageConfig(Color.BLACK, 10);
MatrixToImageWriterEx.writeToFile(matrix, fileType, savePath, logoPath, logoConfig);
+
+
+// BitMatrix matrix = MatrixToImageWriterEx.createQRCode(content, width, height);
+// MatrixToLogoImageConfig logoConfig = new MatrixToLogoImageConfig(Color.BLUE, 4);
+// MatrixToImageWriterEx.writeToFile(matrix, fileType, savePath, logoPath, logoConfig);
}
/**
@@ -79,17 +93,12 @@ public static void encodeLogo(String content, int width, int height, String logo
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static String decode(String filePath) throws IOException, NotFoundException {
- BufferedImage image;
- image = ImageIO.read(new File(filePath));
- if (image == null) {
- return "Could not decode image";
- }
+ BufferedImage image = ImageIO.read(new File(filePath));
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
- Result result;
- Hashtable hints = new Hashtable();
- hints.put(EncodeHintType.CHARACTER_SET, StrConst.DEFAULT_CHARSET_NAME);
- result = new MultiFormatReader().decode(bitmap, hints);
+ Hashtable iis:读取源.true:只向前搜索 描述如何对流进行解码的类 .用于指定如何在输入时从 Java Image I/O 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回
- * ImageReadParam 的实例。
- */
+ * ImageReadParam 的实例。
+ */
ImageReadParam param = reader.getDefaultReadParam();
- /*
+ /*
* 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域,通过 Rectangle 对象 的左上顶点的坐标(x,y)、宽度和高度可以定义这个区域。
- */
+ */
Rectangle rect = new Rectangle(x, y, width, height);
// 提供一个 BufferedImage,将其用作解码像素数据的目标。
param.setSourceRegion(rect);
- /*
+ /*
* 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象,并将 它作为一个完整的 BufferedImage 返回。
- */
+ */
BufferedImage bi = reader.read(0, param);
// 保存新图片
diff --git a/common/src/main/java/pro/tools/data/text/ToolConvert.java b/common/src/main/java/pro/tools/data/text/ToolConvert.java
index 6494072..d258f7a 100644
--- a/common/src/main/java/pro/tools/data/text/ToolConvert.java
+++ b/common/src/main/java/pro/tools/data/text/ToolConvert.java
@@ -21,7 +21,7 @@ public final class ToolConvert {
private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
private ToolConvert() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
@@ -329,9 +329,11 @@ public static byte[] bits2Bytes(String bits) {
int byteLen = bits.length() / 8;
// 不是8的倍数前面补0
if (lenMod != 0) {
+ StringBuilder bitsBuilder = new StringBuilder(bits);
for (int i = lenMod; i < 8; i++) {
- bits = "0" + bits;
+ bitsBuilder.insert(0, "0");
}
+ bits = bitsBuilder.toString();
byteLen++;
}
byte[] bytes = new byte[byteLen];
diff --git a/common/src/main/java/pro/tools/data/text/ToolJson.java b/common/src/main/java/pro/tools/data/text/ToolJson.java
index 9b5f799..c9acdbe 100644
--- a/common/src/main/java/pro/tools/data/text/ToolJson.java
+++ b/common/src/main/java/pro/tools/data/text/ToolJson.java
@@ -2,20 +2,28 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import org.google.gson.Gson;
-import org.google.gson.GsonBuilder;
-import org.google.gson.JsonObject;
-import org.google.gson.reflect.TypeToken;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.reflect.TypeToken;
import pro.tools.data.decimal.Decimal;
import pro.tools.data.text.json.TypeBuilder;
-import pro.tools.data.text.json.typeadapter.*;
+import pro.tools.data.text.json.typeadapter.BigDecimalTypeAdapter;
+import pro.tools.data.text.json.typeadapter.DatePlusTypeAdapter;
+import pro.tools.data.text.json.typeadapter.DecimalTypeAdapter;
+import pro.tools.data.text.json.typeadapter.LocalDateTimeTypeAdapter;
+import pro.tools.data.text.json.typeadapter.LocalDateTypeAdapter;
+import pro.tools.data.text.json.typeadapter.TreeMapTypeAdapter;
import pro.tools.time.DatePlus;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
/**
* 辅助类
@@ -75,6 +83,7 @@ public static GsonBuilder buildSimpleGsonBuilder() {
* 将Map进行JSON编码
*
* @param map
+ *
* @return
*/
public static String mapToJson(Map map) {
@@ -88,6 +97,7 @@ public static String mapToJson(Map map) {
* 将Map进行JSON编码
*
* @param json
+ *
* @return
*/
public static Map jsonToMap(String json) {
@@ -103,6 +113,7 @@ public static Map jsonToMap(String json) {
* 将模型进行JSON编码
*
* @param model
+ *
* @return String
*/
public static S anyToAny(T t, Type type) {
*
* @param data
* @param classOfT
+ *
* @return Object
*/
public static
* 国际数据加密标准---IDEA:完全是新突破,几乎同时和AES出现
+ *
+ * @author SeanDragon
*/
public final class ToolIDEA {
private ToolIDEA() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
@@ -44,8 +46,11 @@ private ToolIDEA() {
/**
* 转换密钥
*
- * @param key 二进制密钥
+ * @param key
+ * 二进制密钥
+ *
* @return Key 密钥
+ *
* @throws Exception
*/
private static Key toKey(byte[] key) {
@@ -58,9 +63,13 @@ private static Key toKey(byte[] key) {
/**
* 解密
*
- * @param data 待解密数据
- * @param key 密钥
+ * @param data
+ * 待解密数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 解密数据
+ *
* @throws Exception
*/
public static byte[] decrypt(byte[] data, byte[] key) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException {
@@ -80,9 +89,13 @@ public static byte[] decrypt(byte[] data, byte[] key) throws InvalidKeyException
/**
* 加密
*
- * @param data 待加密数据
- * @param key 密钥
+ * @param data
+ * 待加密数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 加密数据
+ *
* @throws Exception
*/
public static byte[] encrypt(byte[] data, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
@@ -103,6 +116,7 @@ public static byte[] encrypt(byte[] data, byte[] key) throws NoSuchPaddingExcept
* 生成密钥
*
* @return byte[] 二进制密钥
+ *
* @throws Exception
*/
public static byte[] initKey() throws NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/ToolPBE.java b/security/src/main/java/pro/tools/security/ToolPBE.java
index c9cbaa4..05989b7 100644
--- a/security/src/main/java/pro/tools/security/ToolPBE.java
+++ b/security/src/main/java/pro/tools/security/ToolPBE.java
@@ -20,10 +20,12 @@
*
* 基于口令的加密---PBE:前面的对称加密几乎如出一辙,流程基本一致,PBE综合了对称加密和消息摘要算法的优势,形成对称加密算法的一个特例。没有密钥的概念 * ,使用口令代替密钥 + * + * @author SeanDragon */ public final class ToolPBE { private ToolPBE() { - throw new UnsupportedOperationException("u can't instantiate me..."); + throw new UnsupportedOperationException("我是工具类,别初始化我。。。"); } /** @@ -59,6 +61,7 @@ private ToolPBE() { * 盐长度必须为8字节 * * @return byte[] 盐 + * * @throws Exception */ public static byte[] initSalt() { @@ -69,8 +72,11 @@ public static byte[] initSalt() { /** * 转换密钥 * - * @param password 密码 + * @param password + * 密码 + * * @return Key 密钥 + * * @throws Exception */ private static Key toKey(String password) throws NoSuchAlgorithmException, InvalidKeySpecException { @@ -89,10 +95,15 @@ private static Key toKey(String password) throws NoSuchAlgorithmException, Inval /** * 加密 * - * @param data 数据 - * @param password 密码 - * @param salt 盐 + * @param data + * 数据 + * @param password + * 密码 + * @param salt + * 盐 + * * @return byte[] 加密数据 + * * @throws Exception */ public static byte[] encrypt(byte[] data, String password, byte[] salt) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { @@ -117,10 +128,15 @@ public static byte[] encrypt(byte[] data, String password, byte[] salt) throws I /** * 解密 * - * @param data 数据 - * @param password 密码 - * @param salt 盐 + * @param data + * 数据 + * @param password + * 密码 + * @param salt + * 盐 + * * @return byte[] 解密数据 + * * @throws Exception */ public static byte[] decrypt(byte[] data, String password, byte[] salt) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { diff --git a/security/src/main/java/pro/tools/security/ToolPBE2.java b/security/src/main/java/pro/tools/security/ToolPBE2.java index 32f8905..4338070 100644 --- a/security/src/main/java/pro/tools/security/ToolPBE2.java +++ b/security/src/main/java/pro/tools/security/ToolPBE2.java @@ -16,7 +16,7 @@ */ public final class ToolPBE2 { private ToolPBE2() { - throw new UnsupportedOperationException("u can't instantiate me..."); + throw new UnsupportedOperationException("我是工具类,别初始化我。。。"); } private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1"; @@ -39,26 +39,35 @@ private ToolPBE2() { /** * 对输入的密码进行验证 * - * @param attemptedPassword 待验证的密码 - * @param encryptedPassword 密文 - * @param salt 盐值 + * @param attemptedPassword + * 待验证的密码 + * @param encryptedPassword + * 密文 + * @param salt + * 盐值 + * * @return 是否验证成功 + * * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static boolean authenticate(String attemptedPassword, String encryptedPassword, String salt) throws InvalidKeySpecException, NoSuchAlgorithmException { - // 用相同的盐值对用户输入的密码进行加密 + // 用相同的盐值对用户输入的密码进行加密 String encryptedAttemptedPassword = getEncryptedPassword(attemptedPassword, salt); - // 把加密后的密文和原密文进行比较,相同则验证成功,否则失败 + // 把加密后的密文和原密文进行比较,相同则验证成功,否则失败 return encryptedAttemptedPassword.equals(encryptedPassword); } /** * 生成密文 * - * @param password 明文密码 - * @param salt 盐值 + * @param password + * 明文密码 + * @param salt + * 盐值 + * * @return + * * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ @@ -73,6 +82,7 @@ public static String getEncryptedPassword(String password, String salt) throws N * 通过提供加密的强随机数生成器 生成盐 * * @return + * * @throws NoSuchAlgorithmException */ public static String generateSalt() throws NoSuchAlgorithmException { @@ -85,7 +95,9 @@ public static String generateSalt() throws NoSuchAlgorithmException { /** * 十六进制字符串转二进制字符串 * - * @param hex the hex string + * @param hex + * the hex string + * * @return the hex string decoded into a byte array */ private static byte[] fromHex(String hex) { @@ -99,16 +111,19 @@ private static byte[] fromHex(String hex) { /** * 二进制字符串转十六进制字符串 * - * @param array the byte array to ToolJson + * @param array + * the byte array to ToolJson + * * @return a length*2 character string encoding the byte array */ private static String toHex(byte[] array) { BigInteger bi = new BigInteger(1, array); String hex = bi.toString(16); int paddingLength = (array.length * 2) - hex.length(); - if (paddingLength > 0) + if (paddingLength > 0) { return String.format("%0" + paddingLength + "d", 0) + hex; - else + } else { return hex; + } } } \ No newline at end of file diff --git a/security/src/main/java/pro/tools/security/ToolPbkdf2.java b/security/src/main/java/pro/tools/security/ToolPbkdf2.java index 162c234..f0a7cc1 100644 --- a/security/src/main/java/pro/tools/security/ToolPbkdf2.java +++ b/security/src/main/java/pro/tools/security/ToolPbkdf2.java @@ -20,10 +20,12 @@ * 2.当认证用户的时候,从数据库中取出盐和密文,将他们和明文密码同时传给authenticate(),根据返回结果判断是否认证成功。 *
* 3.当用户修改密码的时候,仍然可以使用原来的盐,只需要调用getEncryptedPassword()方法重新生成密文就可以了。
+ *
+ * @author SeanDragon
*/
public final class ToolPbkdf2 {
private ToolPbkdf2() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
public static boolean authenticate(String attemptedPassword, byte[] encryptedPassword, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
diff --git a/security/src/main/java/pro/tools/security/ToolRSA.java b/security/src/main/java/pro/tools/security/ToolRSA.java
index e22201d..70e8b60 100644
--- a/security/src/main/java/pro/tools/security/ToolRSA.java
+++ b/security/src/main/java/pro/tools/security/ToolRSA.java
@@ -23,11 +23,12 @@
/**
* RSA安全编码组件
+ *
* @author SeanDragon
*/
public final class ToolRSA {
private ToolRSA() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
@@ -53,9 +54,13 @@ private ToolRSA() {
/**
* 私钥解密
*
- * @param data 待解密数据
- * @param key 私钥
+ * @param data
+ * 待解密数据
+ * @param key
+ * 私钥
+ *
* @return byte[] 解密数据
+ *
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
@@ -78,9 +83,13 @@ public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws NoSuchA
/**
* 公钥解密
*
- * @param data 待解密数据
- * @param key 公钥
+ * @param data
+ * 待解密数据
+ * @param key
+ * 公钥
+ *
* @return byte[] 解密数据
+ *
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
@@ -104,9 +113,13 @@ public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws NoSuchAl
/**
* 公钥加密
*
- * @param data 待加密数据
- * @param key 公钥
+ * @param data
+ * 待加密数据
+ * @param key
+ * 公钥
+ *
* @return byte[] 加密数据
+ *
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
@@ -128,9 +141,13 @@ public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws NoSuchAl
/**
* 私钥加密
*
- * @param data 待加密数据
- * @param key 私钥
+ * @param data
+ * 待加密数据
+ * @param key
+ * 私钥
+ *
* @return byte[] 加密数据
+ *
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
@@ -153,8 +170,11 @@ public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws NoSuchA
/**
* 取得私钥
*
- * @param keyMap 密钥Map
+ * @param keyMap
+ * 密钥Map
+ *
* @return byte[] 私钥
+ *
* @throws Exception
*/
public static byte[] getPrivateKey(Map
- * Create By 2017-11-30 16:58
- */
-public class TestMd5 {
- @Test
- public void test1() throws NoSuchAlgorithmException {
- byte [] data = "123456".getBytes();
- long begin = System.currentTimeMillis();
- String result = ToolMD5.encodeMD5Hex(data);
- System.out.println(System.currentTimeMillis()-begin);
- System.out.println(result);
- begin = System.currentTimeMillis();
- HashFunction hashFunction = Hashing.md5();
- Hasher hasher = hashFunction.newHasher();
- hasher.putString("123456", StrConst.DEFAULT_CHARSET);
- HashCode hash = hasher.hash();
- System.out.println(System.currentTimeMillis()-begin);
- System.out.println(hash.toString());
- System.out.println(Hex.toHexString(hash.asBytes()));
- }
-
- @Test
- public void test2() {
- System.out.println(ToolJson.anyToJson(null));
- }
-}
diff --git a/security/src/test/java/TestBarCode.java b/security/src/test/java/TestBarCode.java
new file mode 100644
index 0000000..c18a1e8
--- /dev/null
+++ b/security/src/test/java/TestBarCode.java
@@ -0,0 +1,34 @@
+import com.google.zxing.NotFoundException;
+import com.google.zxing.WriterException;
+import org.junit.Test;
+import pro.tools.data.image.ToolBarCode;
+
+import java.io.IOException;
+import java.util.UUID;
+
+public class TestBarCode {
+
+ String path = "E:/qrcode.png";
+
+ @Test
+ public void test1() throws IOException, WriterException {
+ String str = "425a6839314159265359ad39bc0700007c9ef910067ff03f5f3cf0800a7fffffffffffffff8fe0c0028ec803308654d264d469ea3d2613d434da9899909a3469b44310302000c800d326401a212a7e9e421a53c189a053c34d29e991906a0068c0264320034c118d0e343434340340620680c800034d000d00c80000061228224d3d28fd468434d3ca07a9a32680680001a64f500d34343d468d3d13ca1f2cdf9ebe471be7a9cea7bb0401a2e36812750372948f21a98c90585c1648283a0d41438c2e680e14466e33384322a4e64d126e04084a311b4e522638c46b15d8bb06d99b684060229c03f28129a81080c5b86a1cc38aadc65672230e040525c0b068bc6d32eae630af32fad739b62a475b4ba04a62542106585fc58418633777187460a00d6bff773e0b57bf7e1671c3599661e6414ca081abe6c54bf85f7e562a530d67356877fc70c69307c14d570d7781fcead859b82cd963c320a5f9c70de9dda42e211080c4129fa2b96dd02b9b89c04134e65a47c73cc97b4ea5966cca4ab41bbb48393ed576cd6a985d37f0e6cf31354f32e4236064b6f045291c3a02363e918b146191181796790d0916f655d2ad1d4dd1422be572baab405693c8ca5c00e7e89098c1978d0b3cd2649257273793880b428deb16a5a5495486a4a1a99899c5b704c845254050178c8d2fb44aa18439646ab0bf060e0d2b4de7940ed366546de2d5c695b4c05773b1444a596a1633b48de2536a878ba9d62483fc8439bcdc9dfca91a6c20011626380e24601c271d295196fcd858ac50ed4a7fa42aeabfc94e4a585dfb0b9525e52bf73e82224d929d13b746180ca1472c487f5eba5c592e8f29e0b45428061c63c0c4cd2cf29c554964e16550a54e476f57d1e7157d349ac93f45aa280ab262c5f7a04456935302837002446f1d9f32e753b5830251890e6860cef5b076e013c1c753db2e4a38e4274a0881b45933e09b5dbc599d649051a453723ad56875210b14152b821d6b835eb3c0781523cfe9cf7aecc7f1cfaafcd26cb1823051664a5854a3694edb18537e11403cd27dcc524165305eacd4932e50ff177245385090ad39bc07";
+// ToolBarCode.encode(str,1000,1000,"PNG",path);
+ ToolBarCode.encodeLogo(str, 1000, 1000, "E:/guohui.jfif", "PNG", path);
+ }
+
+ @Test
+ public void test2() throws IOException, NotFoundException {
+ String decode = ToolBarCode.decode(path);
+ System.out.println(decode);
+ }
+
+ @Test
+ public void test3() {
+ int num = 50;
+ for (int i = 0; i < num; i++) {
+ String one = UUID.randomUUID().toString().toUpperCase().replace("-", "");
+ System.out.println(one);
+ }
+ }
+}
\ No newline at end of file
diff --git a/security/src/test/java/package-info.java b/security/src/test/java/package-info.java
new file mode 100644
index 0000000..af10c3e
--- /dev/null
+++ b/security/src/test/java/package-info.java
@@ -0,0 +1 @@
+// 该目录不为空时,删除此文件
\ No newline at end of file
* HmacRipeMD128、HmacRipeMD160共2种算法
+ *
+ * @author SeanDragon
*/
public final class ToolHmacRipeMD {
private ToolHmacRipeMD() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* 初始化HmacRipeMD128密钥
*
* @return byte[] 密钥
+ *
* @throws NoSuchAlgorithmException
*/
public static byte[] initHmacRipeMD128Key() throws NoSuchAlgorithmException {
@@ -45,9 +48,13 @@ public static byte[] initHmacRipeMD128Key() throws NoSuchAlgorithmException {
/**
* HmacRipeMD128消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeHmacRipeMD128(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
@@ -71,9 +78,13 @@ public static byte[] encodeHmacRipeMD128(byte[] data, byte[] key) throws NoSuchA
/**
* HmacRipeMD128Hex消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeHmacRipeMD128Hex(byte[] data, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException {
@@ -89,6 +100,7 @@ public static String encodeHmacRipeMD128Hex(byte[] data, byte[] key) throws Inva
* 初始化HmacRipeMD160密钥
*
* @return byte[] 密钥
+ *
* @throws Exception
*/
public static byte[] initHmacRipeMD160Key() throws NoSuchAlgorithmException {
@@ -109,9 +121,13 @@ public static byte[] initHmacRipeMD160Key() throws NoSuchAlgorithmException {
/**
* HmacRipeMD160消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeHmacRipeMD160(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
@@ -135,9 +151,13 @@ public static byte[] encodeHmacRipeMD160(byte[] data, byte[] key) throws NoSuchA
/**
* HmacRipeMD160Hex消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return String 消息摘要
+ *
* @throws Exception
*/
public static String encodeHmacRipeMD160Hex(byte[] data, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/md/ToolMAC.java b/security/src/main/java/pro/tools/security/md/ToolMAC.java
index 9ec7a9c..d288bca 100644
--- a/security/src/main/java/pro/tools/security/md/ToolMAC.java
+++ b/security/src/main/java/pro/tools/security/md/ToolMAC.java
@@ -10,17 +10,20 @@
/**
* MAC加密组件
+ *
+ * @author SeanDragon
*/
public final class ToolMAC {
private ToolMAC() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* 初始化HmacMD5密钥
*
* @return
+ *
* @throws Exception
*/
public static byte[] initHmacMD5Key() throws NoSuchAlgorithmException {
@@ -38,9 +41,13 @@ public static byte[] initHmacMD5Key() throws NoSuchAlgorithmException {
/**
* HmacMD5加密
*
- * @param data 待加密数据
- * @param key 密钥
+ * @param data
+ * 待加密数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeHmacMD5(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
@@ -62,6 +69,7 @@ public static byte[] encodeHmacMD5(byte[] data, byte[] key) throws NoSuchAlgorit
* 初始化HmacSHA1密钥
*
* @return
+ *
* @throws Exception
*/
public static byte[] initHmacSHAKey() throws NoSuchAlgorithmException {
@@ -79,9 +87,13 @@ public static byte[] initHmacSHAKey() throws NoSuchAlgorithmException {
/**
* HmacSHA1加密
*
- * @param data 待加密数据
- * @param key 密钥
+ * @param data
+ * 待加密数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeHmacSHA(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
@@ -99,13 +111,11 @@ public static byte[] encodeHmacSHA(byte[] data, byte[] key) throws NoSuchAlgorit
return mac.doFinal(data);
}
-// // 根据所安装的 JCE 仲裁策略文件,返回指定转换的最大密钥长度。
-// public final static int getMaxAllowedKeyLength(String transformation)
-
/**
* 初始化HmacSHA256密钥
*
* @return
+ *
* @throws Exception
*/
public static byte[] initHmacSHA256Key() throws NoSuchAlgorithmException {
@@ -123,9 +133,13 @@ public static byte[] initHmacSHA256Key() throws NoSuchAlgorithmException {
/**
* HmacSHA256加密
*
- * @param data 待加密数据
- * @param key 密钥
+ * @param data
+ * 待加密数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeHmacSHA256(byte[] data, byte[] key)
@@ -148,6 +162,7 @@ public static byte[] encodeHmacSHA256(byte[] data, byte[] key)
* 初始化HmacSHA384密钥
*
* @return
+ *
* @throws Exception
*/
public static byte[] initHmacSHA384Key() throws NoSuchAlgorithmException {
@@ -165,9 +180,13 @@ public static byte[] initHmacSHA384Key() throws NoSuchAlgorithmException {
/**
* HmacSHA384加密
*
- * @param data 待加密数据
- * @param key 密钥
+ * @param data
+ * 待加密数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeHmacSHA384(byte[] data, byte[] key)
@@ -190,6 +209,7 @@ public static byte[] encodeHmacSHA384(byte[] data, byte[] key)
* 初始化HmacSHA512密钥
*
* @return
+ *
* @throws Exception
*/
public static byte[] initHmacSHA512Key() throws NoSuchAlgorithmException {
@@ -207,9 +227,13 @@ public static byte[] initHmacSHA512Key() throws NoSuchAlgorithmException {
/**
* HmacSHA512加密
*
- * @param data 待加密数据
- * @param key 密钥
+ * @param data
+ * 待加密数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeHmacSHA512(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
diff --git a/security/src/main/java/pro/tools/security/md/ToolMAC_BCP.java b/security/src/main/java/pro/tools/security/md/ToolMAC_BCP.java
index bb519c8..3579d74 100644
--- a/security/src/main/java/pro/tools/security/md/ToolMAC_BCP.java
+++ b/security/src/main/java/pro/tools/security/md/ToolMAC_BCP.java
@@ -13,17 +13,20 @@
/**
* MAC消息摘要组件
+ *
+ * @author SeanDragon
*/
public final class ToolMAC_BCP {
private ToolMAC_BCP() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* 初始化HmacMD2密钥
*
* @return byte[] 密钥
+ *
* @throws Exception
*/
public static byte[] initHmacMD2Key() throws NoSuchAlgorithmException {
@@ -44,9 +47,13 @@ public static byte[] initHmacMD2Key() throws NoSuchAlgorithmException {
/**
* HmacMD2消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeHmacMD2(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
@@ -70,9 +77,13 @@ public static byte[] encodeHmacMD2(byte[] data, byte[] key) throws NoSuchAlgorit
/**
* HmacMD2Hex消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeHmacMD2Hex(byte[] data, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException {
@@ -88,6 +99,7 @@ public static String encodeHmacMD2Hex(byte[] data, byte[] key) throws InvalidKey
* 初始化HmacMD4密钥
*
* @return byte[] 密钥
+ *
* @throws Exception
*/
public static byte[] initHmacMD4Key() throws NoSuchAlgorithmException {
@@ -108,9 +120,13 @@ public static byte[] initHmacMD4Key() throws NoSuchAlgorithmException {
/**
* HmacMD4消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeHmacMD4(byte[] data, byte[] key)
@@ -135,9 +151,13 @@ public static byte[] encodeHmacMD4(byte[] data, byte[] key)
/**
* HmacMD4Hex消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return String 消息摘要
+ *
* @throws Exception
*/
public static String encodeHmacMD4Hex(byte[] data, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException {
@@ -153,6 +173,7 @@ public static String encodeHmacMD4Hex(byte[] data, byte[] key) throws InvalidKey
* 初始化HmacSHA224密钥
*
* @return byte[] 密钥
+ *
* @throws Exception
*/
public static byte[] initHmacSHA224Key() throws NoSuchAlgorithmException {
@@ -173,9 +194,13 @@ public static byte[] initHmacSHA224Key() throws NoSuchAlgorithmException {
/**
* HmacSHA224消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return byte[] 消息摘要
+ *
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
*/
@@ -200,9 +225,13 @@ public static byte[] encodeHmacSHA224(byte[] data, byte[] key) throws NoSuchAlgo
/**
* HmacSHA224Hex消息摘要
*
- * @param data 待做消息摘要处理的数据
- * @param key 密钥
+ * @param data
+ * 待做消息摘要处理的数据
+ * @param key
+ * 密钥
+ *
* @return String 消息摘要
+ *
* @throws Exception
*/
public static String encodeHmacSHA224Hex(byte[] data, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/md/ToolMD.java b/security/src/main/java/pro/tools/security/md/ToolMD.java
index bdebcaf..f154dd6 100644
--- a/security/src/main/java/pro/tools/security/md/ToolMD.java
+++ b/security/src/main/java/pro/tools/security/md/ToolMD.java
@@ -10,19 +10,24 @@
/**
* MD系列加密组件
* Tiger、Whirlpool和GOST3411共3种算法
+ *
+ * @author SeanDragon
*/
public final class ToolMD {
private ToolMD() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* Tiger加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeTiger(byte[] data) throws NoSuchAlgorithmException {
@@ -40,8 +45,11 @@ public static byte[] encodeTiger(byte[] data) throws NoSuchAlgorithmException {
/**
* TigerHex加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeTigerHex(byte[] data) throws NoSuchAlgorithmException {
@@ -56,8 +64,11 @@ public static String encodeTigerHex(byte[] data) throws NoSuchAlgorithmException
/**
* Whirlpool加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeWhirlpool(byte[] data) throws NoSuchAlgorithmException {
@@ -75,8 +86,11 @@ public static byte[] encodeWhirlpool(byte[] data) throws NoSuchAlgorithmExceptio
/**
* WhirlpoolHex加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeWhirlpoolHex(byte[] data) throws NoSuchAlgorithmException {
@@ -91,8 +105,11 @@ public static String encodeWhirlpoolHex(byte[] data) throws NoSuchAlgorithmExcep
/**
* GOST3411加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeGOST3411(byte[] data) throws NoSuchAlgorithmException {
@@ -110,8 +127,11 @@ public static byte[] encodeGOST3411(byte[] data) throws NoSuchAlgorithmException
/**
* GOST3411Hex加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeGOST3411Hex(byte[] data) throws NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/md/ToolMD2.java b/security/src/main/java/pro/tools/security/md/ToolMD2.java
index 55885e7..742bbe3 100644
--- a/security/src/main/java/pro/tools/security/md/ToolMD2.java
+++ b/security/src/main/java/pro/tools/security/md/ToolMD2.java
@@ -7,17 +7,22 @@
/**
* MD加密组件
+ *
+ * @author SeanDragon
*/
public final class ToolMD2 {
private ToolMD2() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* MD2加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeMD2(byte[] data) throws NoSuchAlgorithmException {
@@ -31,8 +36,11 @@ public static byte[] encodeMD2(byte[] data) throws NoSuchAlgorithmException {
/**
* MD2加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeMD2Hex(byte[] data) throws NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/md/ToolMD4.java b/security/src/main/java/pro/tools/security/md/ToolMD4.java
index d0e738f..f538c6d 100644
--- a/security/src/main/java/pro/tools/security/md/ToolMD4.java
+++ b/security/src/main/java/pro/tools/security/md/ToolMD4.java
@@ -9,17 +9,22 @@
/**
* MD4加密组件
+ *
+ * @author SeanDragon
*/
public final class ToolMD4 {
private ToolMD4() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* MD4加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeMD4(byte[] data) throws NoSuchAlgorithmException {
@@ -37,8 +42,11 @@ public static byte[] encodeMD4(byte[] data) throws NoSuchAlgorithmException {
/**
* MD4加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return String 消息摘要
+ *
* @throws Exception
*/
public static String encodeMD4Hex(byte[] data) throws NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/md/ToolMD5.java b/security/src/main/java/pro/tools/security/md/ToolMD5.java
index 43141fa..9718689 100644
--- a/security/src/main/java/pro/tools/security/md/ToolMD5.java
+++ b/security/src/main/java/pro/tools/security/md/ToolMD5.java
@@ -9,17 +9,22 @@
/**
* MD5加密组件
+ *
+ * @author SeanDragon
*/
public final class ToolMD5 {
private ToolMD5() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* MD5加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws NoSuchAlgorithmException
*/
public static byte[] encodeMD5(byte[] data) throws NoSuchAlgorithmException {
@@ -36,8 +41,11 @@ public static byte[] encodeMD5(byte[] data) throws NoSuchAlgorithmException {
/**
* MD5加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return String 消息摘要
+ *
* @throws NoSuchAlgorithmException
*/
public static String encodeMD5Hex(byte[] data) throws NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/md/ToolRipeMD.java b/security/src/main/java/pro/tools/security/md/ToolRipeMD.java
index 80147a8..57f31ea 100644
--- a/security/src/main/java/pro/tools/security/md/ToolRipeMD.java
+++ b/security/src/main/java/pro/tools/security/md/ToolRipeMD.java
@@ -10,17 +10,22 @@
/**
* RipeMD系列消息摘要组件
* 包含RipeMD128、RipeMD160、RipeMD256和RipeMD320共4种RipeMD系列算法
+ *
+ * @author SeanDragon
*/
public final class ToolRipeMD {
private ToolRipeMD() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* RipeMD128消息摘要
*
- * @param data 待做消息摘要处理的数据
+ * @param data
+ * 待做消息摘要处理的数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeRipeMD128(byte[] data) throws NoSuchAlgorithmException {
@@ -38,8 +43,11 @@ public static byte[] encodeRipeMD128(byte[] data) throws NoSuchAlgorithmExceptio
/**
* RipeMD128Hex消息摘要
*
- * @param data 待做消息摘要处理的数据
+ * @param data
+ * 待做消息摘要处理的数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeRipeMD128Hex(byte[] data) throws NoSuchAlgorithmException {
@@ -54,8 +62,11 @@ public static String encodeRipeMD128Hex(byte[] data) throws NoSuchAlgorithmExcep
/**
* RipeMD160消息摘要
*
- * @param data 待做消息摘要处理的数据
+ * @param data
+ * 待做消息摘要处理的数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeRipeMD160(byte[] data) throws NoSuchAlgorithmException {
@@ -73,8 +84,11 @@ public static byte[] encodeRipeMD160(byte[] data) throws NoSuchAlgorithmExceptio
/**
* RipeMD160Hex消息摘要
*
- * @param data 待做消息摘要处理的数据
+ * @param data
+ * 待做消息摘要处理的数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeRipeMD160Hex(byte[] data) throws NoSuchAlgorithmException {
@@ -89,8 +103,11 @@ public static String encodeRipeMD160Hex(byte[] data) throws NoSuchAlgorithmExcep
/**
* RipeMD256消息摘要
*
- * @param data 待做消息摘要处理的数据
+ * @param data
+ * 待做消息摘要处理的数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeRipeMD256(byte[] data) throws NoSuchAlgorithmException {
@@ -108,8 +125,11 @@ public static byte[] encodeRipeMD256(byte[] data) throws NoSuchAlgorithmExceptio
/**
* RipeMD256Hex消息摘要
*
- * @param data 待做消息摘要处理的数据
+ * @param data
+ * 待做消息摘要处理的数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeRipeMD256Hex(byte[] data) throws NoSuchAlgorithmException {
@@ -124,8 +144,11 @@ public static String encodeRipeMD256Hex(byte[] data) throws NoSuchAlgorithmExcep
/**
* RipeMD320消息摘要
*
- * @param data 待做消息摘要处理的数据
+ * @param data
+ * 待做消息摘要处理的数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeRipeMD320(byte[] data) throws NoSuchAlgorithmException {
@@ -143,8 +166,11 @@ public static byte[] encodeRipeMD320(byte[] data) throws NoSuchAlgorithmExceptio
/**
* RipeMD320Hex消息摘要
*
- * @param data 待做消息摘要处理的数据
+ * @param data
+ * 待做消息摘要处理的数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeRipeMD320Hex(byte[] data) throws NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/md/ToolSHA1.java b/security/src/main/java/pro/tools/security/md/ToolSHA1.java
index abe1b35..7a8479b 100644
--- a/security/src/main/java/pro/tools/security/md/ToolSHA1.java
+++ b/security/src/main/java/pro/tools/security/md/ToolSHA1.java
@@ -7,17 +7,22 @@
/**
* SHA-1加密
+ *
+ * @author SeanDragon
*/
public final class ToolSHA1 {
private ToolSHA1() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* SHA-1加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeSHA(byte[] data) throws NoSuchAlgorithmException {
@@ -31,8 +36,11 @@ public static byte[] encodeSHA(byte[] data) throws NoSuchAlgorithmException {
/**
* SHA-1加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeSHAHex(byte[] data) throws NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/md/ToolSHA2.java b/security/src/main/java/pro/tools/security/md/ToolSHA2.java
index 77d9189..ce530ad 100644
--- a/security/src/main/java/pro/tools/security/md/ToolSHA2.java
+++ b/security/src/main/java/pro/tools/security/md/ToolSHA2.java
@@ -9,17 +9,22 @@
/**
* SHA-2 的变种 SHA- 224、 SHA- 256、 SHA-384 、 SHA-512
+ *
+ * @author SeanDragon
*/
public final class ToolSHA2 {
private ToolSHA2() {
- throw new UnsupportedOperationException("u can't instantiate me...");
+ throw new UnsupportedOperationException("我是工具类,别初始化我。。。");
}
/**
* SHA-224加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeSHA224(byte[] data) throws NoSuchAlgorithmException {
@@ -36,8 +41,11 @@ public static byte[] encodeSHA224(byte[] data) throws NoSuchAlgorithmException {
/**
* SHA-224加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeSHA224Hex(byte[] data) throws NoSuchAlgorithmException {
@@ -51,8 +59,11 @@ public static String encodeSHA224Hex(byte[] data) throws NoSuchAlgorithmExceptio
/**
* SHA-256加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeSHA256(byte[] data) throws NoSuchAlgorithmException {
@@ -66,8 +77,11 @@ public static byte[] encodeSHA256(byte[] data) throws NoSuchAlgorithmException {
/**
* SHA-256加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeSHA256Hex(byte[] data) throws NoSuchAlgorithmException {
@@ -81,8 +95,11 @@ public static String encodeSHA256Hex(byte[] data) throws NoSuchAlgorithmExceptio
/**
* SHA-384加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeSHA384(byte[] data) throws NoSuchAlgorithmException {
@@ -96,8 +113,11 @@ public static byte[] encodeSHA384(byte[] data) throws NoSuchAlgorithmException {
/**
* SHA-384加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeSHA384Hex(byte[] data) throws NoSuchAlgorithmException {
@@ -111,8 +131,11 @@ public static String encodeSHA384Hex(byte[] data) throws NoSuchAlgorithmExceptio
/**
* SHA-512加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static byte[] encodeSHA512(byte[] data) throws NoSuchAlgorithmException {
@@ -126,8 +149,11 @@ public static byte[] encodeSHA512(byte[] data) throws NoSuchAlgorithmException {
/**
* SHA-512加密
*
- * @param data 待加密数据
+ * @param data
+ * 待加密数据
+ *
* @return byte[] 消息摘要
+ *
* @throws Exception
*/
public static String encodeSHA512Hex(byte[] data) throws NoSuchAlgorithmException {
diff --git a/security/src/main/java/pro/tools/security/sm/SM2.java b/security/src/main/java/pro/tools/security/sm/SM2.java
new file mode 100644
index 0000000..3f7c594
--- /dev/null
+++ b/security/src/main/java/pro/tools/security/sm/SM2.java
@@ -0,0 +1,729 @@
+package pro.tools.security.sm;
+
+import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECPoint;
+
+import java.io.*;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Arrays;
+
+/**
+ * SM2公钥加密算法实现 包括 -签名,验签 -密钥交换 -公钥加密,私钥解密
+ *
+ * @author SeanDragon
+ */
+public class SM2 {
+ private static final int DIGEST_LENGTH = 32;
+ private static BigInteger n = new BigInteger(
+ "FFFFFFFE" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "7203DF6B" + "21C6052B" + "53BBF409" + "39D54123", 16);
+ private static BigInteger p = new BigInteger(
+ "FFFFFFFE" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "00000000" + "FFFFFFFF" + "FFFFFFFF", 16);
+ private static BigInteger a = new BigInteger(
+ "FFFFFFFE" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "00000000" + "FFFFFFFF" + "FFFFFFFC", 16);
+ private static BigInteger b = new BigInteger(
+ "28E9FA9E" + "9D9F5E34" + "4D5A9E4B" + "CF6509A7" + "F39789F5" + "15AB8F92" + "DDBCBD41" + "4D940E93", 16);
+ private static BigInteger gx = new BigInteger(
+ "32C4AE2C" + "1F198119" + "5F990446" + "6A39C994" + "8FE30BBF" + "F2660BE1" + "715A4589" + "334C74C7", 16);
+ private static BigInteger gy = new BigInteger(
+ "BC3736A2" + "F4F6779C" + "59BDCEE3" + "6B692153" + "D0A9877C" + "C62A4740" + "02DF32E5" + "2139F0A0", 16);
+ private static ECDomainParameters ecc_bc_spec;
+ private static int w = (int) Math.ceil(n.bitLength() * 1.0 / 2) - 1;
+ private static BigInteger _2w = new BigInteger("2").pow(w);
+ private static SecureRandom random = new SecureRandom();
+ private static ECCurve.Fp curve;
+ private static ECPoint G;
+
+ public SM2() {
+ curve = new ECCurve.Fp(p, // q
+ a, // a
+ b); // b
+ G = curve.createPoint(gx, gy);
+ ecc_bc_spec = new ECDomainParameters(curve, G, n);
+ }
+
+ /**
+ * 以16进制打印字节数组
+ *
+ * @param bytes
+ */
+ private static void printHexString(byte[] bytes) {
+ for (byte b : bytes) {
+ String hex = Integer.toHexString(b & 0xFF);
+ if (hex.length() == 1) {
+ hex = '0' + hex;
+ }
+ System.out.print(hex.toUpperCase());
+ }
+ System.out.println();
+ }
+
+ /**
+ * 随机数生成器
+ *
+ * @param max
+ * @return
+ */
+ private static BigInteger random(BigInteger max) {
+ BigInteger r = new BigInteger(256, random);
+ while (r.compareTo(max) >= 0) {
+ r = new BigInteger(128, random);
+ }
+ return r;
+ }
+
+ /**
+ * 字节数组拼接
+ *
+ * @param params
+ * @return
+ */
+ private static byte[] join(byte[]... params) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] res = null;
+ try {
+ for (int i = 0; i < params.length; i++) {
+ baos.write(params[i]);
+ }
+ res = baos.toByteArray();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return res;
+ }
+
+ /**
+ * sm3摘要
+ *
+ * @param params
+ * @return
+ */
+ private static byte[] sm3hash(byte[]... params) {
+ byte[] res = null;
+ try {
+ res = SM3.hash(join(params));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return res;
+ }
+
+ // /**
+ // * SHA摘要
+ // * @param x2
+ // * @param M
+ // * @param y2
+ // * @return
+ // */
+ // private byte[] calculateHash(BigInteger x2, byte[] M, BigInteger y2) {
+ // ShortenedDigest digest = new ShortenedDigest(new SHA256Digest(),
+ // DIGEST_LENGTH);
+ // byte[] buf = x2.toByteArray();
+ // digest.update(buf, 0, buf.length);
+ // digest.update(M, 0, M.length);
+ // buf = y2.toByteArray();
+ // digest.update(buf, 0, buf.length);
+ //
+ // buf = new byte[DIGEST_LENGTH];
+ // digest.doFinal(buf, 0);
+ //
+ // return buf;
+ // }
+
+ /**
+ * 取得用户标识字节数组
+ *
+ * @param IDA
+ * @param aPublicKey
+ * @return
+ */
+ private static byte[] ZA(String IDA, ECPoint aPublicKey) {
+ byte[] idaBytes = IDA.getBytes();
+ int entlenA = idaBytes.length * 8;
+ byte[] ENTLA = new byte[]{(byte) (entlenA & 0xFF00), (byte) (entlenA & 0x00FF)};
+ byte[] ZA = sm3hash(ENTLA, idaBytes, a.toByteArray(), b.toByteArray(), gx.toByteArray(), gy.toByteArray(),
+ aPublicKey.getXCoord().toBigInteger().toByteArray(),
+ aPublicKey.getYCoord().toBigInteger().toByteArray());
+ return ZA;
+ }
+
+ /**
+ * 密钥派生函数
+ *
+ * @param Z
+ * @param klen 生成klen字节数长度的密钥
+ * @return
+ */
+ private static byte[] KDF(byte[] Z, int klen) {
+ int ct = 1;
+ int end = (int) Math.ceil(klen * 1.0 / 32);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ for (int i = 1; i < end; i++) {
+ baos.write(sm3hash(Z, SM3.toByteArray(ct)));
+ ct++;
+ }
+ byte[] last = sm3hash(Z, SM3.toByteArray(ct));
+ if (klen % 32 == 0) {
+ baos.write(last);
+ } else {
+ baos.write(last, 0, klen % 32);
+ }
+ return baos.toByteArray();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 判断字节数组是否全0
+ *
+ * @param buffer
+ * @return
+ */
+ private boolean allZero(byte[] buffer) {
+ for (byte aBuffer : buffer) {
+ if (aBuffer != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 公钥加密
+ *
+ * @param input 加密原文
+ * @param publicKey 公钥
+ * @return
+ */
+ public byte[] encrypt(String input, ECPoint publicKey) {
+
+ byte[] inputBuffer = input.getBytes();
+
+ byte[] C1Buffer;
+ ECPoint kpb;
+ byte[] t;
+ do {
+ /* 1 产生随机数k,k属于[1, n-1] */
+ BigInteger k = random(n);
+
+ /* 2 计算椭圆曲线点C1 = [k]G = (x1, y1) */
+ ECPoint C1 = G.multiply(k);
+ C1Buffer = C1.getEncoded(false);
+
+ /*
+ * 3 计算椭圆曲线点 S = [h]Pb
+ */
+ BigInteger h = ecc_bc_spec.getH();
+ if (h != null) {
+ ECPoint S = publicKey.multiply(h);
+ if (S.isInfinity()) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /* 4 计算 [k]PB = (x2, y2) */
+ kpb = publicKey.multiply(k).normalize();
+
+ /* 5 计算 t = KDF(x2||y2, klen) */
+ byte[] kpbBytes = kpb.getEncoded(false);
+ t = KDF(kpbBytes, inputBuffer.length);
+ // DerivationFunction kdf = new KDF1BytesGenerator(new
+ // ShortenedDigest(new SHA256Digest(), DIGEST_LENGTH));
+ //
+ // t = new byte[inputBuffer.length];
+ // kdf.init(new ISO18033KDFParameters(kpbBytes));
+ // kdf.generateBytes(t, 0, t.length);
+ } while (allZero(t));
+
+ /* 6 计算C2=M^t */
+ byte[] C2 = new byte[inputBuffer.length];
+ for (int i = 0; i < inputBuffer.length; i++) {
+ C2[i] = (byte) (inputBuffer[i] ^ t[i]);
+ }
+
+ /* 7 计算C3 = Hash(x2 || M || y2) */
+ byte[] C3 = sm3hash(kpb.getXCoord().toBigInteger().toByteArray(), inputBuffer,
+ kpb.getYCoord().toBigInteger().toByteArray());
+
+ /* 8 输出密文 C=C1 || C2 || C3 */
+
+ byte[] encryptResult = new byte[C1Buffer.length + C2.length + C3.length];
+
+ System.arraycopy(C1Buffer, 0, encryptResult, 0, C1Buffer.length);
+ System.arraycopy(C2, 0, encryptResult, C1Buffer.length, C2.length);
+ System.arraycopy(C3, 0, encryptResult, C1Buffer.length + C2.length, C3.length);
+
+ return encryptResult;
+ }
+
+ /**
+ * 私钥解密
+ *
+ * @param encryptData 密文数据字节数组
+ * @param privateKey 解密私钥
+ * @return
+ */
+ public String decrypt(byte[] encryptData, BigInteger privateKey) {
+
+ byte[] C1Byte = new byte[65];
+ System.arraycopy(encryptData, 0, C1Byte, 0, C1Byte.length);
+
+ ECPoint C1 = curve.decodePoint(C1Byte).normalize();
+
+ /*
+ * 计算椭圆曲线点 S = [h]C1 是否为无穷点
+ */
+ BigInteger h = ecc_bc_spec.getH();
+ if (h != null) {
+ ECPoint S = C1.multiply(h);
+ if (S.isInfinity()) {
+ throw new IllegalStateException();
+ }
+ }
+ /* 计算[dB]C1 = (x2, y2) */
+ ECPoint dBC1 = C1.multiply(privateKey).normalize();
+
+ /* 计算t = KDF(x2 || y2, klen) */
+ byte[] dBC1Bytes = dBC1.getEncoded(false);
+ int klen = encryptData.length - 65 - DIGEST_LENGTH;
+ byte[] t = KDF(dBC1Bytes, klen);
+ // DerivationFunction kdf = new KDF1BytesGenerator(new
+ // ShortenedDigest(new SHA256Digest(), DIGEST_LENGTH));
+ // if (debug)
+ // System.out.println("klen = " + klen);
+ // kdf.init(new ISO18033KDFParameters(dBC1Bytes));
+ // kdf.generateBytes(t, 0, t.length);
+
+ if (allZero(t)) {
+ System.err.println("all zero");
+ throw new IllegalStateException();
+ }
+
+ /* 5 计算M'=C2^t */
+ byte[] M = new byte[klen];
+ for (int i = 0; i < M.length; i++) {
+ M[i] = (byte) (encryptData[C1Byte.length + i] ^ t[i]);
+ }
+ /* 6 计算 u = Hash(x2 || M' || y2) 判断 u == C3是否成立 */
+ byte[] C3 = new byte[DIGEST_LENGTH];
+
+ System.arraycopy(encryptData, encryptData.length - DIGEST_LENGTH, C3, 0, DIGEST_LENGTH);
+ byte[] u = sm3hash(dBC1.getXCoord().toBigInteger().toByteArray(), M,
+ dBC1.getYCoord().toBigInteger().toByteArray());
+ if (Arrays.equals(u, C3)) {
+ try {
+ return new String(M, "UTF8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return null;
+ } else {
+ return null;
+ }
+
+ }
+
+ /**
+ * 判断是否在范围内
+ *
+ * @param param
+ * @param min
+ * @param max
+ * @return
+ */
+ private boolean between(BigInteger param, BigInteger min, BigInteger max) {
+ if (param.compareTo(min) >= 0 && param.compareTo(max) < 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * 判断生成的公钥是否合法
+ *
+ * @param publicKey
+ * @return
+ */
+ private boolean checkPublicKey(ECPoint publicKey) {
+
+ if (!publicKey.isInfinity()) {
+
+ BigInteger x = publicKey.getXCoord().toBigInteger();
+ BigInteger y = publicKey.getYCoord().toBigInteger();
+
+ if (between(x, new BigInteger("0"), p) && between(y, new BigInteger("0"), p)) {
+
+ BigInteger xResult = x.pow(3).add(a.multiply(x)).add(b).mod(p);
+
+ BigInteger yResult = y.pow(2).mod(p);
+
+ return yResult.equals(xResult) && publicKey.multiply(n).isInfinity();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 生成密钥对
+ *
+ * @return
+ */
+ public SM2KeyPair generateKeyPair() {
+
+ BigInteger d = random(n.subtract(new BigInteger("1")));
+
+ SM2KeyPair keyPair = new SM2KeyPair(G.multiply(d).normalize(), d);
+
+ if (checkPublicKey(keyPair.getPublicKey())) {
+ return keyPair;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * 导出公钥到本地
+ *
+ * @param publicKey
+ * @param path
+ */
+ public void exportPublicKey(ECPoint publicKey, String path) {
+ File file = new File(path);
+ try {
+ if (!file.exists()) {
+ file.createNewFile();
+ }
+ byte buffer[] = publicKey.getEncoded(false);
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(buffer);
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 从本地导入公钥
+ *
+ * @param path
+ * @return
+ */
+ public ECPoint importPublicKey(String path) {
+ File file = new File(path);
+ try {
+ if (!file.exists()) {
+ return null;
+ }
+ FileInputStream fis = new FileInputStream(file);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ byte buffer[] = new byte[16];
+ int size;
+ while ((size = fis.read(buffer)) != -1) {
+ baos.write(buffer, 0, size);
+ }
+ fis.close();
+ return curve.decodePoint(baos.toByteArray());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 导出私钥到本地
+ *
+ * @param privateKey
+ * @param path
+ */
+ public void exportPrivateKey(BigInteger privateKey, String path) {
+ File file = new File(path);
+ try {
+ if (!file.exists()) {
+ file.createNewFile();
+ }
+ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
+ oos.writeObject(privateKey);
+ oos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 从本地导入私钥
+ *
+ * @param path
+ * @return
+ */
+ public BigInteger importPrivateKey(String path) {
+ File file = new File(path);
+ try {
+ if (!file.exists()) {
+ return null;
+ }
+ FileInputStream fis = new FileInputStream(file);
+ ObjectInputStream ois = new ObjectInputStream(fis);
+ BigInteger res = (BigInteger) (ois.readObject());
+ ois.close();
+ fis.close();
+ return res;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 签名
+ *
+ * @param M 签名信息
+ * @param IDA 签名方唯一标识
+ * @param keyPair 签名方密钥对
+ * @return 签名
+ */
+ public Signature sign(String M, String IDA, SM2KeyPair keyPair) {
+ byte[] ZA = ZA(IDA, keyPair.getPublicKey());
+ byte[] M_ = join(ZA, M.getBytes());
+ BigInteger e = new BigInteger(1, sm3hash(M_));
+ // BigInteger k = new BigInteger(
+ // "6CB28D99 385C175C 94F94E93 4817663F C176D925 DD72B727 260DBAAE
+ // 1FB2F96F".replace(" ", ""), 16);
+ BigInteger k;
+ BigInteger r;
+ do {
+ k = random(n);
+ ECPoint p1 = G.multiply(k).normalize();
+ BigInteger x1 = p1.getXCoord().toBigInteger();
+ r = e.add(x1);
+ r = r.mod(n);
+ } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n));
+
+ BigInteger s = ((keyPair.getPrivateKey().add(BigInteger.ONE).modInverse(n))
+ .multiply((k.subtract(r.multiply(keyPair.getPrivateKey()))).mod(n))).mod(n);
+
+ return new Signature(r, s);
+ }
+
+ /**
+ * 验签
+ *
+ * @param M 签名信息
+ * @param signature 签名
+ * @param IDA 签名方唯一标识
+ * @param aPublicKey 签名方公钥
+ * @return true or false
+ */
+ public boolean verify(String M, Signature signature, String IDA, ECPoint aPublicKey) {
+ if (!between(signature.r, BigInteger.ONE, n)) {
+ return false;
+ }
+ if (!between(signature.s, BigInteger.ONE, n)) {
+ return false;
+ }
+
+ byte[] M_ = join(ZA(IDA, aPublicKey), M.getBytes());
+ BigInteger e = new BigInteger(1, sm3hash(M_));
+ BigInteger t = signature.r.add(signature.s).mod(n);
+
+ if (t.equals(BigInteger.ZERO)) {
+ return false;
+ }
+
+ ECPoint p1 = G.multiply(signature.s).normalize();
+ ECPoint p2 = aPublicKey.multiply(t).normalize();
+ BigInteger x1 = p1.add(p2).normalize().getXCoord().toBigInteger();
+ BigInteger R = e.add(x1).mod(n);
+ if (R.equals(signature.r)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 传输实体类
+ *
+ * @author SeanDragon
+ */
+ private static class TransportEntity implements Serializable {
+ final byte[] R; //R点
+ final byte[] S; //验证S
+ final byte[] Z; //用户标识
+ final byte[] K; //公钥
+
+ public TransportEntity(byte[] r, byte[] s, byte[] z, ECPoint pKey) {
+ R = r;
+ S = s;
+ Z = z;
+ K = pKey.getEncoded(false);
+ }
+ }
+
+ /**
+ * 密钥协商辅助类
+ *
+ * @author SeanDragon
+ */
+ public static class KeyExchange {
+ BigInteger rA;
+ ECPoint RA;
+ ECPoint V;
+ byte[] Z;
+ byte[] key;
+
+ String ID;
+ SM2KeyPair keyPair;
+
+ public KeyExchange(String ID, SM2KeyPair keyPair) {
+ this.ID = ID;
+ this.keyPair = keyPair;
+ this.Z = ZA(ID, keyPair.getPublicKey());
+ }
+
+ /**
+ * 密钥协商发起第一步
+ *
+ * @return
+ */
+ public TransportEntity keyExchange_1() {
+ rA = random(n);
+ // rA=new BigInteger("83A2C9C8 B96E5AF7 0BD480B4 72409A9A 327257F1
+ // EBB73F5B 073354B2 48668563".replace(" ", ""),16);
+ RA = G.multiply(rA).normalize();
+ return new TransportEntity(RA.getEncoded(false), null, Z, keyPair.getPublicKey());
+ }
+
+ /**
+ * 密钥协商响应方
+ *
+ * @param entity 传输实体
+ * @return
+ */
+ public TransportEntity keyExchange_2(TransportEntity entity) {
+ BigInteger rB = random(n);
+ // BigInteger rB=new BigInteger("33FE2194 0342161C 55619C4A 0C060293
+ // D543C80A F19748CE 176D8347 7DE71C80".replace(" ", ""),16);
+ ECPoint RB = G.multiply(rB).normalize();
+
+ this.rA = rB;
+ this.RA = RB;
+
+ BigInteger x2 = RB.getXCoord().toBigInteger();
+ x2 = _2w.add(x2.and(_2w.subtract(BigInteger.ONE)));
+
+ BigInteger tB = keyPair.getPrivateKey().add(x2.multiply(rB)).mod(n);
+ ECPoint RA = curve.decodePoint(entity.R).normalize();
+
+ BigInteger x1 = RA.getXCoord().toBigInteger();
+ x1 = _2w.add(x1.and(_2w.subtract(BigInteger.ONE)));
+
+ ECPoint aPublicKey = curve.decodePoint(entity.K).normalize();
+ ECPoint temp = aPublicKey.add(RA.multiply(x1).normalize()).normalize();
+ ECPoint V = temp.multiply(ecc_bc_spec.getH().multiply(tB)).normalize();
+ if (V.isInfinity()) {
+ throw new IllegalStateException();
+ }
+ this.V = V;
+
+ byte[] xV = V.getXCoord().toBigInteger().toByteArray();
+ byte[] yV = V.getYCoord().toBigInteger().toByteArray();
+ byte[] KB = KDF(join(xV, yV, entity.Z, this.Z), 16);
+ key = KB;
+ System.out.print("协商得B密钥:");
+ printHexString(KB);
+ byte[] sB = sm3hash(new byte[]{0x02}, yV,
+ sm3hash(xV, entity.Z, this.Z, RA.getXCoord().toBigInteger().toByteArray(),
+ RA.getYCoord().toBigInteger().toByteArray(), RB.getXCoord().toBigInteger().toByteArray(),
+ RB.getYCoord().toBigInteger().toByteArray()));
+ return new TransportEntity(RB.getEncoded(false), sB, this.Z, keyPair.getPublicKey());
+ }
+
+ /**
+ * 密钥协商发起方第二步
+ *
+ * @param entity 传输实体
+ */
+ public TransportEntity keyExchange_3(TransportEntity entity) {
+ BigInteger x1 = RA.getXCoord().toBigInteger();
+ x1 = _2w.add(x1.and(_2w.subtract(BigInteger.ONE)));
+
+ BigInteger tA = keyPair.getPrivateKey().add(x1.multiply(rA)).mod(n);
+ ECPoint RB = curve.decodePoint(entity.R).normalize();
+
+ BigInteger x2 = RB.getXCoord().toBigInteger();
+ x2 = _2w.add(x2.and(_2w.subtract(BigInteger.ONE)));
+
+ ECPoint bPublicKey = curve.decodePoint(entity.K).normalize();
+ ECPoint temp = bPublicKey.add(RB.multiply(x2).normalize()).normalize();
+ ECPoint U = temp.multiply(ecc_bc_spec.getH().multiply(tA)).normalize();
+ if (U.isInfinity()) {
+ throw new IllegalStateException();
+ }
+ this.V = U;
+
+ byte[] xU = U.getXCoord().toBigInteger().toByteArray();
+ byte[] yU = U.getYCoord().toBigInteger().toByteArray();
+ byte[] KA = KDF(join(xU, yU,
+ this.Z, entity.Z), 16);
+ key = KA;
+ System.out.print("协商得A密钥:");
+ printHexString(KA);
+ byte[] s1 = sm3hash(new byte[]{0x02}, yU,
+ sm3hash(xU, this.Z, entity.Z, RA.getXCoord().toBigInteger().toByteArray(),
+ RA.getYCoord().toBigInteger().toByteArray(), RB.getXCoord().toBigInteger().toByteArray(),
+ RB.getYCoord().toBigInteger().toByteArray()));
+ if (Arrays.equals(entity.S, s1)) {
+ System.out.println("B->A 密钥确认成功");
+ } else {
+ System.out.println("B->A 密钥确认失败");
+ }
+ byte[] sA = sm3hash(new byte[]{0x03}, yU,
+ sm3hash(xU, this.Z, entity.Z, RA.getXCoord().toBigInteger().toByteArray(),
+ RA.getYCoord().toBigInteger().toByteArray(), RB.getXCoord().toBigInteger().toByteArray(),
+ RB.getYCoord().toBigInteger().toByteArray()));
+
+ return new TransportEntity(RA.getEncoded(false), sA, this.Z, keyPair.getPublicKey());
+ }
+
+ /**
+ * 密钥确认最后一步
+ *
+ * @param entity 传输实体
+ */
+ public void keyExchange_4(TransportEntity entity) {
+ byte[] xV = V.getXCoord().toBigInteger().toByteArray();
+ byte[] yV = V.getYCoord().toBigInteger().toByteArray();
+ ECPoint RA = curve.decodePoint(entity.R).normalize();
+ byte[] s2 = sm3hash(new byte[]{0x03}, yV,
+ sm3hash(xV, entity.Z, this.Z, RA.getXCoord().toBigInteger().toByteArray(),
+ RA.getYCoord().toBigInteger().toByteArray(), this.RA.getXCoord().toBigInteger().toByteArray(),
+ this.RA.getYCoord().toBigInteger().toByteArray()));
+ if (Arrays.equals(entity.S, s2)) {
+ System.out.println("A->B 密钥确认成功");
+ } else {
+ System.out.println("A->B 密钥确认失败");
+ }
+ }
+ }
+
+ public static class Signature {
+ BigInteger r;
+ BigInteger s;
+
+ Signature(BigInteger r, BigInteger s) {
+ this.r = r;
+ this.s = s;
+ }
+
+ @Override
+ public String toString() {
+ return r.toString(16) + "," + s.toString(16);
+ }
+ }
+}
\ No newline at end of file
diff --git a/security/src/main/java/pro/tools/security/sm/SM2KeyPair.java b/security/src/main/java/pro/tools/security/sm/SM2KeyPair.java
new file mode 100644
index 0000000..ceea124
--- /dev/null
+++ b/security/src/main/java/pro/tools/security/sm/SM2KeyPair.java
@@ -0,0 +1,30 @@
+package pro.tools.security.sm;
+
+import org.bouncycastle.math.ec.ECPoint;
+
+import java.math.BigInteger;
+
+/**
+ * SM2密钥对
+ *
+ * @author SeanDragon
+ */
+public class SM2KeyPair {
+
+ private final ECPoint publicKey;
+ private final BigInteger privateKey;
+
+ SM2KeyPair(ECPoint publicKey, BigInteger privateKey) {
+ this.publicKey = publicKey;
+ this.privateKey = privateKey;
+ }
+
+ public ECPoint getPublicKey() {
+ return publicKey;
+ }
+
+ public BigInteger getPrivateKey() {
+ return privateKey;
+ }
+
+}
\ No newline at end of file
diff --git a/security/src/main/java/pro/tools/security/sm/SM3.java b/security/src/main/java/pro/tools/security/sm/SM3.java
new file mode 100644
index 0000000..471a646
--- /dev/null
+++ b/security/src/main/java/pro/tools/security/sm/SM3.java
@@ -0,0 +1,207 @@
+package pro.tools.security.sm;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Arrays;
+
+/**
+ * SM3杂凑算法实现
+ *
+ * @author SeanDragon
+ */
+public class SM3 {
+
+ private static final String ivHexStr = "7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e";
+ private static final BigInteger IV = new BigInteger(ivHexStr.replaceAll(" ",
+ ""), 16);
+ private static final Integer Tj15 = Integer.valueOf("79cc4519", 16);
+ private static final Integer Tj63 = Integer.valueOf("7a879d8a", 16);
+ private static final byte[] FirstPadding = {(byte) 0x80};
+ private static final byte[] ZeroPadding = {(byte) 0x00};
+ private static char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ private static int T(int j) {
+ if (j >= 0 && j <= 15) {
+ return Tj15;
+ } else if (j >= 16 && j <= 63) {
+ return Tj63;
+ } else {
+ throw new RuntimeException("data invalid");
+ }
+ }
+
+ private static Integer FF(Integer x, Integer y, Integer z, int j) {
+ if (j >= 0 && j <= 15) {
+ return x ^ y ^ z;
+ } else if (j >= 16 && j <= 63) {
+ return (x & y)
+ | (x & z)
+ | (y & z);
+ } else {
+ throw new RuntimeException("data invalid");
+ }
+ }
+
+ private static Integer GG(Integer x, Integer y, Integer z, int j) {
+ if (j >= 0 && j <= 15) {
+ return x ^ y ^ z;
+ } else if (j >= 16 && j <= 63) {
+ return (x & y) | (~x & z);
+ } else {
+ throw new RuntimeException("data invalid");
+ }
+ }
+
+ private static Integer P0(Integer x) {
+ return x
+ ^ Integer.rotateLeft(x, 9)
+ ^ Integer.rotateLeft(x, 17);
+ }
+
+ private static Integer P1(Integer x) {
+ return x
+ ^ Integer.rotateLeft(x, 15)
+ ^ Integer.rotateLeft(x, 23);
+ }
+
+ private static byte[] padding(byte[] source) throws IOException {
+ long l = source.length * 8;
+ long k = 448 - (l + 1) % 512;
+ if (k < 0) {
+ k = k + 512;
+ }
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ baos.write(source);
+ baos.write(FirstPadding);
+ long i = k - 7;
+ while (i > 0) {
+ baos.write(ZeroPadding);
+ i -= 8;
+ }
+ baos.write(long2bytes(l));
+ return baos.toByteArray();
+ }
+
+ private static byte[] long2bytes(long l) {
+ byte[] bytes = new byte[8];
+ for (int i = 0; i < 8; i++) {
+ bytes[i] = (byte) (l >>> ((7 - i) * 8));
+ }
+ return bytes;
+ }
+
+ static byte[] hash(byte[] source) throws IOException {
+ byte[] m1 = padding(source);
+ int n = m1.length / (512 / 8);
+ byte[] b;
+ byte[] vi = IV.toByteArray();
+ byte[] vi1 = null;
+ for (int i = 0; i < n; i++) {
+ b = Arrays.copyOfRange(m1, i * 64, (i + 1) * 64);
+ vi1 = CF(vi, b);
+ vi = vi1;
+ }
+ return vi1;
+ }
+
+ private static byte[] CF(byte[] vi, byte[] bi) throws IOException {
+ int a, b, c, d, e, f, g, h;
+ a = toInteger(vi, 0);
+ b = toInteger(vi, 1);
+ c = toInteger(vi, 2);
+ d = toInteger(vi, 3);
+ e = toInteger(vi, 4);
+ f = toInteger(vi, 5);
+ g = toInteger(vi, 6);
+ h = toInteger(vi, 7);
+
+ int[] w = new int[68];
+ int[] w1 = new int[64];
+ for (int i = 0; i < 16; i++) {
+ w[i] = toInteger(bi, i);
+ }
+ for (int j = 16; j < 68; j++) {
+ w[j] = P1(w[j - 16] ^ w[j - 9] ^ Integer.rotateLeft(w[j - 3], 15))
+ ^ Integer.rotateLeft(w[j - 13], 7) ^ w[j - 6];
+ }
+ for (int j = 0; j < 64; j++) {
+ w1[j] = w[j] ^ w[j + 4];
+ }
+ int ss1, ss2, tt1, tt2;
+ for (int j = 0; j < 64; j++) {
+ ss1 = Integer
+ .rotateLeft(
+ Integer.rotateLeft(a, 12) + e
+ + Integer.rotateLeft(T(j), j), 7);
+ ss2 = ss1 ^ Integer.rotateLeft(a, 12);
+ tt1 = FF(a, b, c, j) + d + ss2 + w1[j];
+ tt2 = GG(e, f, g, j) + h + ss1 + w[j];
+ d = c;
+ c = Integer.rotateLeft(b, 9);
+ b = a;
+ a = tt1;
+ h = g;
+ g = Integer.rotateLeft(f, 19);
+ f = e;
+ e = P0(tt2);
+ }
+ byte[] v = toByteArray(a, b, c, d, e, f, g, h);
+ for (int i = 0; i < v.length; i++) {
+ v[i] = (byte) (v[i] ^ vi[i]);
+ }
+ return v;
+ }
+
+ private static int toInteger(byte[] source, int index) {
+ StringBuilder valueStr = new StringBuilder();
+ for (int i = 0; i < 4; i++) {
+ valueStr.append(hexDigits[(byte) ((source[index * 4 + i] & 0xF0) >> 4)]);
+ valueStr.append(hexDigits[(byte) (source[index * 4 + i] & 0x0F)]);
+ }
+ return Long.valueOf(valueStr.toString(), 16).intValue();
+
+ }
+
+ private static byte[] toByteArray(int a, int b, int c, int d, int e, int f,
+ int g, int h) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(32);
+ baos.write(toByteArray(a));
+ baos.write(toByteArray(b));
+ baos.write(toByteArray(c));
+ baos.write(toByteArray(d));
+ baos.write(toByteArray(e));
+ baos.write(toByteArray(f));
+ baos.write(toByteArray(g));
+ baos.write(toByteArray(h));
+ return baos.toByteArray();
+ }
+
+ static byte[] toByteArray(int i) {
+ byte[] byteArray = new byte[4];
+ byteArray[0] = (byte) (i >>> 24);
+ byteArray[1] = (byte) ((i & 0xFFFFFF) >>> 16);
+ byteArray[2] = (byte) ((i & 0xFFFF) >>> 8);
+ byteArray[3] = (byte) (i & 0xFF);
+ return byteArray;
+ }
+
+ private static String byteToHexString(byte b) {
+ int n = b;
+ if (n < 0) {
+ n = 256 + n;
+ }
+ int d1 = n / 16;
+ int d2 = n % 16;
+ return "" + hexDigits[d1] + hexDigits[d2];
+ }
+
+ public static String byteArrayToHexString(byte[] b) {
+ StringBuilder resultSb = new StringBuilder();
+ for (byte aB : b) {
+ resultSb.append(byteToHexString(aB));
+ }
+ return resultSb.toString();
+ }
+}
\ No newline at end of file
diff --git a/security/src/main/test/TestMd5.java b/security/src/main/test/TestMd5.java
deleted file mode 100644
index 1ac45eb..0000000
--- a/security/src/main/test/TestMd5.java
+++ /dev/null
@@ -1,40 +0,0 @@
-import com.google.common.hash.HashCode;
-import com.google.common.hash.HashFunction;
-import com.google.common.hash.Hasher;
-import com.google.common.hash.Hashing;
-import org.bouncycastle.util.encoders.Hex;
-import org.junit.Test;
-import pro.tools.constant.StrConst;
-import pro.tools.data.text.ToolJson;
-import pro.tools.security.md.ToolMD5;
-
-import java.security.NoSuchAlgorithmException;
-
-/**
- * @author SeanDragon
- *