diff --git a/common/src/main/java/com/jeesite/common/codec/DigestUtils.java b/common/src/main/java/com/jeesite/common/codec/DigestUtils.java index 60012644..56c1b806 100644 --- a/common/src/main/java/com/jeesite/common/codec/DigestUtils.java +++ b/common/src/main/java/com/jeesite/common/codec/DigestUtils.java @@ -4,15 +4,13 @@ */ package com.jeesite.common.codec; +import com.jeesite.common.lang.ExceptionUtils; +import org.apache.commons.lang3.Validate; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + import java.io.IOException; import java.io.InputStream; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.SecureRandom; - -import org.apache.commons.lang3.Validate; - -import com.jeesite.common.lang.ExceptionUtils; +import java.security.*; /** * 不可逆加密工具类 @@ -20,11 +18,15 @@ import com.jeesite.common.lang.ExceptionUtils; */ public class DigestUtils { - private static SecureRandom random = new SecureRandom(); + public static final String SHA1 = "SHA-1"; + public static final String MD5 = "MD5"; + public static final String SM3 = "SM3"; + + private static final SecureRandom random = new SecureRandom(); /** - * 生成随机的Byte[]作为salt密钥. - * @param numBytes byte数组的大小 + * 生成随机的 Byte[] 作为 salt 密钥. + * @param numBytes byte 数组的大小 */ public static byte[] genSalt(int numBytes) { Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes); @@ -32,25 +34,41 @@ public class DigestUtils { random.nextBytes(bytes); return bytes; } + + /** + * 生成随机的 Byte[] 作为 salt 密钥,返回 HEX 值 + * @param numBytes byte 数组的大小 + */ + public static String genSaltString(int numBytes) { + return EncodeUtils.encodeHex(genSalt(numBytes)); + } + + /** + * 获取 MessageDigest + */ + private static MessageDigest getMessageDigest(String algorithm) throws GeneralSecurityException { + if (SM3.equals(algorithm)) { + return MessageDigest.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME); + } else { + return MessageDigest.getInstance(algorithm); + } + } /** * 对字符串进行散列, 支持md5与sha1算法. * @param input 需要散列的字符串 - * @param algorithm 散列算法("SHA-1"、"MD5") - * @param salt + * @param algorithm 散列算法("SHA-1"、"MD5"、"SM3") + * @param salt 可为空 * @param iterations 迭代次数 * @return */ public static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) { try { - MessageDigest digest = MessageDigest.getInstance(algorithm); - + MessageDigest digest = getMessageDigest(algorithm); if (salt != null) { digest.update(salt); } - byte[] result = digest.digest(input); - for (int i = 1; i < iterations; i++) { digest.reset(); result = digest.digest(result); @@ -64,20 +82,18 @@ public class DigestUtils { /** * 对文件进行sha1散列. * @param input 需要散列的流 - * @param algorithm 散列算法("SHA-1"、"MD5") + * @param algorithm 散列算法("SHA-1"、"MD5"、"SM3") */ public static byte[] digest(InputStream input, String algorithm) throws IOException { try { - MessageDigest messageDigest = MessageDigest.getInstance(algorithm); + MessageDigest messageDigest = getMessageDigest(algorithm); int bufferLength = 8 * 1024; byte[] buffer = new byte[bufferLength]; int read = input.read(buffer, 0, bufferLength); - while (read > -1) { messageDigest.update(buffer, 0, read); read = input.read(buffer, 0, bufferLength); } - return messageDigest.digest(); } catch (GeneralSecurityException e) { throw ExceptionUtils.unchecked(e); diff --git a/common/src/main/java/com/jeesite/common/codec/EncodeUtils.java b/common/src/main/java/com/jeesite/common/codec/EncodeUtils.java index c88954f8..c2bcca5a 100644 --- a/common/src/main/java/com/jeesite/common/codec/EncodeUtils.java +++ b/common/src/main/java/com/jeesite/common/codec/EncodeUtils.java @@ -26,11 +26,11 @@ import java.util.regex.Pattern; /** * 封装各种格式的编码解码工具类. - * 1.Commons-Codec的 hex/base64 编码 - * 2.自制的base62 编码 - * 3.Commons-Lang的xml/html escape - * 4.JDK提供的URLEncoder - * 5、XSS、SQL、orderBy 过滤器 + * 1. Commons-Codec 的 hex/base64 编码 + * 2. 自制的 base62 编码 + * 3. Commons-Lang 的 xml/html escape + * 4. JDK 提供的 URLEncoder + * 5. XSS、SQL、orderBy 过滤器 * @author calvin、ThinkGem * @version 2022-2-17 */ @@ -304,38 +304,4 @@ public class EncodeUtils { return null; } -// public static void main(String[] args) { -// xssFilter("1 你好 我还在。"); -// xssFilter("2 你好 加粗文字我还在。"); -// xssFilter("3 你好 \">加粗文字我还在。"); -// xssFilter("4 你好 加粗文字我还在。"); -// xssFilter("5 你好 我还在。"); -// xssFilter("14 你好 eval(abc)我还在。"); -// xssFilter("15 你好 expression(abc)我还在。"); -// xssFilter("16 你好 我还在。"); -// xssFilter("17 你好 我还在。"); -// xssFilter("18 你好 我还在。"); -// xssFilter("19 你好 hello我还在。"); -// xssFilter("20 你好 hello我还在。"); -// xssFilter("21 你好 hello我还在。"); -// xssFilter("22 你好 hello我还在。"); -// xssFilter("23 你好 hello我还在。"); -// xssFilter("24 你好 ?abc=def&hello=123&world={\"a\":1}我还在。"); -// xssFilter("25 你好 ?abc=def&hello=123&world={'a':1}我还在。"); -// sqlFilter("1 你好 select * from xxx where abc=def and 1=1我还在。"); -// sqlFilter("2 你好 insert into xxx values(1,2,3,4,5)我还在。"); -// sqlFilter("3 你好 delete from xxx我还在。"); -// sqlFilter("4 a.audit_result asc,case when 1 like case when length(database())=6 then 1 else exp(111) end then 1 else 1/0 end", "orderBy"); -// sqlFilter("5 if(1=2,1,SLEEP(10)), if(mid(database(),{},1)=\\\"{}\\\",a.id,a.login_name)", "orderBy"); -// sqlFilter("6 a.audit_result asc, b.audit_result2 desc, b.AuditResult3 desc", "orderBy"); -// } - } diff --git a/common/src/main/java/com/jeesite/common/codec/Md5Utils.java b/common/src/main/java/com/jeesite/common/codec/Md5Utils.java index 5a730a88..9471664a 100644 --- a/common/src/main/java/com/jeesite/common/codec/Md5Utils.java +++ b/common/src/main/java/com/jeesite/common/codec/Md5Utils.java @@ -4,22 +4,25 @@ */ package com.jeesite.common.codec; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.io.UnsupportedEncodingException; - import com.jeesite.common.lang.StringUtils; +import java.io.*; +import java.nio.charset.StandardCharsets; + /** * MD5不可逆加密工具类 * @author ThinkGem */ public class Md5Utils { - - private static final String MD5 = "MD5"; + /** + * 对输入字符串进行md5散列. + * @param input 加密字符串 + */ + public static byte[] md5(byte[] input) { + return md5(input, 1); + } + /** * 对输入字符串进行md5散列. * @param input 加密字符串 @@ -33,36 +36,24 @@ public class Md5Utils { * @param input 加密字符串 * @param iterations 迭代次数 */ - public static String md5(String input, int iterations) { - try { - return EncodeUtils.encodeHex(DigestUtils.digest(input.getBytes(EncodeUtils.UTF_8), MD5, null, iterations)); - } catch (UnsupportedEncodingException e) { - return StringUtils.EMPTY; - } + public static byte[] md5(byte[] input, int iterations) { + return DigestUtils.digest(input, DigestUtils.MD5, null, iterations); } - - /** - * 对输入字符串进行md5散列. - * @param input 加密字符串 - */ - public static byte[] md5(byte[] input) { - return md5(input, 1); - } - + /** * 对输入字符串进行md5散列. * @param input 加密字符串 * @param iterations 迭代次数 */ - public static byte[] md5(byte[] input, int iterations) { - return DigestUtils.digest(input, MD5, null, iterations); + public static String md5(String input, int iterations) { + return EncodeUtils.encodeHex(DigestUtils.digest(input.getBytes(StandardCharsets.UTF_8), DigestUtils.MD5, null, iterations)); } /** * 对文件进行md5散列. */ public static byte[] md5(InputStream input) throws IOException { - return DigestUtils.digest(input, MD5); + return DigestUtils.digest(input, DigestUtils.MD5); } /** diff --git a/common/src/test/java/com/jeesite/test/codec/AesUtilsTest.java b/common/src/test/java/com/jeesite/test/codec/AesUtilsTest.java new file mode 100644 index 00000000..a4421d01 --- /dev/null +++ b/common/src/test/java/com/jeesite/test/codec/AesUtilsTest.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.test.codec; + +import com.jeesite.common.codec.AesUtils; +import com.jeesite.common.codec.EncodeUtils; + +import java.nio.charset.StandardCharsets; + +/** + * AES 加密解密工具类 + * @author ThinkGem + * @version 2024-07-22 + */ +public class AesUtilsTest { + + public static void main(String[] args) { + + String s = "Hello word! 你好,中文!"; + System.out.println(s); + + String k = AesUtils.genKeyString(); + System.out.println(k); + String s1 = AesUtils.encode(s, k); + System.out.println(s1); + String s2 = AesUtils.decode(s1, k); + System.out.println(s2); + + byte[] key = AesUtils.genKey(); + byte[] iv = AesUtils.genIV(); + byte[] data = AesUtils.encode(s.getBytes(StandardCharsets.UTF_8), key, iv); + System.out.println(EncodeUtils.encodeHex(data)); + byte[] data2 = AesUtils.decode(data, key, iv); + System.out.println(new String(data2, StandardCharsets.UTF_8)); + } + +} \ No newline at end of file diff --git a/common/src/test/java/com/jeesite/test/codec/EncodeUtilsTest.java b/common/src/test/java/com/jeesite/test/codec/EncodeUtilsTest.java new file mode 100644 index 00000000..de24d4f0 --- /dev/null +++ b/common/src/test/java/com/jeesite/test/codec/EncodeUtilsTest.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.test.codec; + +import com.jeesite.common.codec.EncodeUtils; + +/** + * 封装各种格式的编码解码工具测试类 + * @author ThinkGem + * @version 2024-07-22 + */ +public class EncodeUtilsTest { + + public static void main(String[] args) { + EncodeUtils.xssFilter("1 你好 我还在。"); + EncodeUtils.xssFilter("2 你好 加粗文字我还在。"); + EncodeUtils.xssFilter("3 你好 \">加粗文字我还在。"); + EncodeUtils.xssFilter("4 你好 加粗文字我还在。"); + EncodeUtils.xssFilter("5 你好 我还在。"); + EncodeUtils.xssFilter("14 你好 eval(abc)我还在。"); + EncodeUtils.xssFilter("15 你好 expression(abc)我还在。"); + EncodeUtils.xssFilter("16 你好 我还在。"); + EncodeUtils.xssFilter("17 你好 我还在。"); + EncodeUtils.xssFilter("18 你好 我还在。"); + EncodeUtils.xssFilter("19 你好 hello我还在。"); + EncodeUtils.xssFilter("20 你好 hello我还在。"); + EncodeUtils.xssFilter("21 你好 hello我还在。"); + EncodeUtils.xssFilter("22 你好 hello我还在。"); + EncodeUtils.xssFilter("23 你好 hello我还在。"); + EncodeUtils.xssFilter("24 你好 ?abc=def&hello=123&world={\"a\":1}我还在。"); + EncodeUtils.xssFilter("25 你好 ?abc=def&hello=123&world={'a':1}我还在。"); + EncodeUtils.sqlFilter("1 你好 select * from xxx where abc=def and 1=1我还在。"); + EncodeUtils.sqlFilter("2 你好 insert into xxx values(1,2,3,4,5)我还在。"); + EncodeUtils.sqlFilter("3 你好 delete from xxx我还在。"); + EncodeUtils.sqlFilter("4 a.audit_result asc,case when 1 like case when length(database())=6 then 1 else exp(111) end then 1 else 1/0 end", "orderBy"); + EncodeUtils.sqlFilter("5 if(1=2,1,SLEEP(10)), if(mid(database(),{},1)=\\\"{}\\\",a.id,a.login_name)", "orderBy"); + EncodeUtils.sqlFilter("6 a.audit_result asc, b.audit_result2 desc, b.AuditResult3 desc", "orderBy"); + } + +} diff --git a/common/src/test/java/com/jeesite/test/codec/Sha1UtilsTest.java b/common/src/test/java/com/jeesite/test/codec/Sha1UtilsTest.java new file mode 100644 index 00000000..02656dc0 --- /dev/null +++ b/common/src/test/java/com/jeesite/test/codec/Sha1UtilsTest.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.test.codec; + +import com.jeesite.common.codec.Sha1Utils; + +/** + * SHA-1 加密工具类,散列加密,不可逆加密 + * @author ThinkGem + * @version 2024-07-22 + */ +public class Sha1UtilsTest { + + public static void main(String[] args) { + + String s = "Hello word! 你好,中文!"; + System.out.println(s); + + String salt = Sha1Utils.genSaltString(8); + System.out.println(salt); + String data = Sha1Utils.sha1(s, salt); + System.out.println(data); + + } + +} \ No newline at end of file