This commit is contained in:
clay
2024-03-06 17:44:09 +08:00
commit adaec0eadd
1493 changed files with 219939 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.fateverse</groupId>
<artifactId>common</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>common-decrypt</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>cn.fateverse</groupId>
<artifactId>common-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,36 @@
package cn.fateverse.common.decrypt;
import cn.fateverse.common.decrypt.aspect.EncryptAspect;
import cn.fateverse.common.decrypt.config.EncryptProperties;
import cn.fateverse.common.decrypt.service.DefaultEncryptService;
import cn.fateverse.common.decrypt.service.EncryptService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* @author Clay
* @date 2023-07-04
*/
@EnableConfigurationProperties({EncryptProperties.class})
public class DecryptConfiguration {
@Bean
@ConditionalOnMissingBean({EncryptService.class})
public EncryptService encryptService(EncryptProperties encryptProperties) {
return new DefaultEncryptService(encryptProperties);
}
@Bean
@ConditionalOnBean(EncryptService.class)
public EncryptAspect encryptAspect(EncryptService encryptService) {
return new EncryptAspect(encryptService);
}
}

View File

@@ -0,0 +1,15 @@
package cn.fateverse.common.decrypt.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Clay
* @date 2023-07-03
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Encrypt {
}

View File

@@ -0,0 +1,14 @@
package cn.fateverse.common.decrypt.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定义注解 标记需要加密的字段
*/
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptField {
}

View File

@@ -0,0 +1,156 @@
package cn.fateverse.common.decrypt.aspect;
import cn.fateverse.common.core.exception.CustomException;
import cn.fateverse.common.core.result.Result;
import cn.fateverse.common.decrypt.annotation.EncryptField;
import cn.fateverse.common.decrypt.service.EncryptService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.util.ReflectionUtils;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Collection;
import java.util.List;
@Slf4j
@Aspect
public class EncryptAspect {
protected static String BASE_PACKAGE;
static {
String typeName = EncryptAspect.class.getTypeName();
int fastIndex = typeName.indexOf(".");
BASE_PACKAGE = typeName.substring(0, typeName.indexOf(".", fastIndex + 1));
}
private final EncryptService encryptService;
public EncryptAspect(EncryptService encryptService) {
this.encryptService = encryptService;
}
@Around("@annotation(cn.fateverse.common.decrypt.annotation.Encrypt)")
public Object decryptField(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
//获取请求参数
Object[] args = point.getArgs();
//获取方法
Method method = signature.getMethod();
//获取方法参数 Parameter对象集 参数修饰符、参数名、注解及注解类型
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
//获取参数注解
EncryptField encryptField = parameter.getAnnotation(EncryptField.class);
Object arg = args[i];
if (null != encryptField) {
if (arg instanceof String) {
String decrypt = encryptService.decrypt((String) arg);
args[i] = decrypt;
} else if (arg instanceof List) {
try {
List<String> list = (List<String>) arg;
for (int j = 0; j < list.size(); j++) {
String ciphertext = list.get(j);
String decrypt = encryptService.decrypt(ciphertext);
list.set(j, decrypt);
}
args[i] = list;
} catch (Exception e) {
throw new CustomException("接受参数类型错误,请使用String类型的泛型参数");
}
}
} else if (parameter.getType().getName().startsWith(BASE_PACKAGE)) { //返回一个类对象,该类对象标识此参数对象表示的参数的声明类型
decrypt(arg);
}
}
//正常执行业务最后返回的返回值为Result
Object proceed = point.proceed(args);
if (proceed instanceof Result) {
Result<Object> result = (Result<Object>) proceed;
Object data = result.getData();
if (null != data) {
try {
encrypt(data);
} catch (Exception e) {
log.error("加密异常", e);
return Result.error("加密异常!");
}
}
result.setData(data);
} else {
try {
encrypt(proceed);
} catch (Exception e) {
log.error("加密异常", e);
return Result.error("加密异常!");
}
}
return proceed;
}
private void encrypt(Object data) throws Exception {
if (data == null) {
return;
}
Class<?> argClass = data.getClass();
if (argClass.getTypeName().startsWith(BASE_PACKAGE)) {
Field[] fields = argClass.getDeclaredFields();
for (Field field : fields) {
EncryptField encryptField = field.getAnnotation(EncryptField.class);
field.setAccessible(true);
Object value = ReflectionUtils.getField(field, data);
if (null == value) {
continue;
}
if (null != encryptField && value instanceof String) {
String decrypt = encryptService.encrypt((String) value);
ReflectionUtils.setField(field, data, decrypt);
} else if (field.getType().getName().startsWith(BASE_PACKAGE)) {
encrypt(value);
} else if (value instanceof Collection) {
Collection<Object> collection = (Collection<Object>) value;
for (Object item : collection) {
encrypt(item);
}
}
}
} else if (data instanceof Collection) {
Collection<Object> collection = (Collection<Object>) data;
for (Object item : collection) {
encrypt(item);
}
}
}
private void decrypt(Object arg) throws Exception {
Class<?> argClass = arg.getClass();
Field[] fields = argClass.getDeclaredFields();
for (Field field : fields) {
EncryptField encryptField = field.getAnnotation(EncryptField.class);
field.setAccessible(true);
Object value = ReflectionUtils.getField(field, arg);
if (null == value) {
continue;
}
if (null != encryptField && value instanceof String) {
String decrypt = encryptService.decrypt((String) value);
ReflectionUtils.setField(field, arg, decrypt);
} else if (field.getType().getName().startsWith(BASE_PACKAGE)) {
decrypt(value);
}
}
}
}

View File

@@ -0,0 +1,21 @@
package cn.fateverse.common.decrypt.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author Clay
* @date 2023-07-04
*/
@ConfigurationProperties(prefix = "encrypt")
public class EncryptProperties {
private String secretKey = "1234567890abcdef";
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
}

View File

@@ -0,0 +1,41 @@
package cn.fateverse.common.decrypt.service;
import cn.fateverse.common.core.exception.CustomException;
import cn.fateverse.common.decrypt.config.EncryptProperties;
import cn.fateverse.common.decrypt.utils.SM4Util;
import javax.annotation.Resource;
/**
* @author Clay
* @date 2023-08-07
*/
public class DefaultEncryptService implements EncryptService {
private final EncryptProperties properties;
public DefaultEncryptService(EncryptProperties properties) {
this.properties = properties;
}
@Override
public String encrypt(String plainText) {
try {
return SM4Util.encrypt(plainText, properties.getSecretKey());
} catch (Exception e) {
throw new CustomException("加密失败", e);
}
}
@Override
public String decrypt(String cipherText) {
try {
return SM4Util.decrypt(cipherText, properties.getSecretKey());
} catch (Exception e) {
throw new CustomException("解密失败", e);
}
}
}

View File

@@ -0,0 +1,24 @@
package cn.fateverse.common.decrypt.service;
/**
* @author Clay
* @date 2024/2/19 16:19
*/
public interface EncryptService {
/**
* 加密方法
*
* @param plainText 需要加密的文档
* @return 加密之后的数据
*/
String encrypt(String plainText);
/**
* 解密方法
*
* @param cipherText 需要解密的文档
* @return 解密之后的文档
*/
String decrypt(String cipherText);
}

View File

@@ -0,0 +1,115 @@
package cn.fateverse.common.decrypt.utils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
public class SM4Util {
private static final String ALGORITHM_NAME = "SM4";
private static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS7Padding";
private static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS7Padding";
private static final String CHARSET_NAME = "UTF-8";
private static final String IV_PARAMETER = "0000000000000000";
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* SM4 加密
*
* @param plainText 明文
* @param secretKey 密钥
* @return 密文
* @throws Exception 异常
*/
public static String encrypt(String plainText, String secretKey) throws Exception {
byte[] keyBytes = secretKey.getBytes(CHARSET_NAME);
byte[] plainBytes = plainText.getBytes(CHARSET_NAME);
byte[] cipherBytes = encrypt_ECB_Padding(keyBytes, plainBytes);
return new String(Hex.encode(cipherBytes));
}
/**
* SM4 解密
*
* @param cipherText 密文
* @param secretKey 密钥
* @return 明文
* @throws Exception 异常
*/
public static String decrypt(String cipherText, String secretKey) throws Exception {
byte[] keyBytes = secretKey.getBytes(CHARSET_NAME);
byte[] cipherBytes = Hex.decode(cipherText);
byte[] plainBytes = decrypt_ECB_Padding(keyBytes, cipherBytes);
return new String(plainBytes, CHARSET_NAME);
}
/**
* ECB 模式加密
*
* @param keyBytes 密钥
* @param plainBytes 明文
* @return 密文
* @throws Exception 异常
*/
private static byte[] encrypt_ECB_Padding(byte[] keyBytes, byte[] plainBytes) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM_NAME);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(plainBytes);
}
/**
* ECB 模式解密
*
* @param keyBytes 密钥
* @param cipherBytes 密文
* @return 明文
* @throws Exception 异常
*/
private static byte[] decrypt_ECB_Padding(byte[] keyBytes, byte[] cipherBytes) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM_NAME);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
return cipher.doFinal(cipherBytes);
}
/**
* CBC 模式加密
*
* @param keyBytes 密钥
* @param plainBytes 明文
* @param ivBytes 向量
* @return 密文
* @throws Exception 异常
*/
private static byte[] encrypt_CBC_Padding(byte[] keyBytes, byte[] plainBytes, byte[] ivBytes) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_CBC_PADDING, BouncyCastleProvider.PROVIDER_NAME);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM_NAME);
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher.doFinal(plainBytes);
}
/**
* CBC 模式解密
*
* @param keyBytes 密钥
* @param cipherBytes 密文
* @param ivBytes 向量
* @return 明文
* @throws Exception 异常
*/
private static byte[] decrypt_CBC_Padding(byte[] keyBytes, byte[] cipherBytes, byte[] ivBytes) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_CBC_PADDING, BouncyCastleProvider.PROVIDER_NAME);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM_NAME); IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); return cipher.doFinal(cipherBytes);
}
}

View File

@@ -0,0 +1 @@
cn.fateverse.common.decrypt.DecryptConfiguration