diff --git a/README.md b/README.md index d0acd8dd82b4295ab5ad9093f406daff549041a4..943e854a80c29824540d99ffc9f2b6c747c9309c 100644 --- a/README.md +++ b/README.md @@ -1,681 +1,134 @@ -# **encrypt-spring-boot-starter** -## maven坐标 - ```xml - - cloud.longfa - encrypt-spring-boot-starter - 1.0.6-RELEASE - - ``` - -WEB应用加解密请查看此根目录WEBAPP.md文档 配套使用 - -## 实现方案 - -aop、反射机制、递归算法 、策略模式 - -## 优势 - -1. **全注解、支持spel表达式(改造过,易用)、支持任意字段、任意参数、任意请求方式** -2. **支持多种场景(传输场景、存储场景)** -3. **支持扩展其他场景(已经实现网络传输、存储加解密)** -4. **支持扩展其他的加密算法** -5. **支持的加密模式:单类算法加密(多参数单算法)、多类算法混合(单参数|字段单算法)、混合模式(单参数 多种算法)、混合模式之随机密钥** -6. **支持任意请求方式 、任意多个参数、body 支持java集合、实体类等等** -7. **支持RPC框架 实现前端后、端对端数据加密** -8. **支持任意多个字段|参数 任意多种加密算法同时用** - -## 数据加密 场景启动器 - -### 支持的场景 - -#### 一 、传输场景加密解密 - -网络传输后端加减密 *前端加解密没空写* - -支持RPC框架 远程调用 多种算法混合使用 能控制到每一个字段 都使用独立的算法 不必担心解不了密!!! 怎么加怎么解 - -#### 二 、存储场景 加密解密 - -支持存储加解密 多种算法混合使用 - -## 支持的请求方式 - -任意请求方式 不仅仅只是争对body 也支持请求参数(任意个) - -## 层级要求 - -无限层 支持无限套娃!!! - -比如集合嵌套集合 支持多层级嵌套 -## 支持的加密模式 - -支持的加密算法 AES、RSA、SM4 混合加密 动态密钥混合加密 同时也支持扩展其他算法 - -1. 单模式加密: - - 一个接口只使用一种加密算法 - -2. 多种算法单模式 +# encrypt-spring-boot-starter - 一个接口下每一个参数使用单独的加密算法 +`encrypt-spring-boot-starter` 是一个专为 Spring Boot 项目打造的数据加密解密框架,提供便捷的注解式加密与解密能力,适用于数据传输和数据存储场景。 -3. 混合加密: +## 特性 - 两种以上的加密算法融合使用 密钥使用自己配置的 +- **多种加密算法支持**:支持 AES、SM4、RSA 等主流加密算法。 +- **灵活的使用方式**:支持简单注解使用、SpEL 表达式、混合加密等多种使用模式。 +- **两大核心场景**: + - 数据传输加密解密(前后端分离项目中请求和响应的加密处理) + - 数据存储加密解密(数据库存储前加密、读取时解密) -4. 动态混合加密: +## 安装说明 - 密钥是随机生成 每一次请求密钥都是不一样 提供了外部获取密钥的方式 +### Maven 引入 -## 目录结构 - -老版本: - -``` -├─src -│ └─main -│ ├─java -│ │ └─cloud -│ │ └─longfa -│ │ └─encrypt -│ │ ├─anotation -│ │ │ Decrypt.java 加密注解 -│ │ │ EnableEncrypt.java 导入模块注解 -│ │ │ Encrypt.java 解密注解 -│ │ │ -│ │ ├─aspectj -│ │ │ EncryptHandler.java 注解处理器 aop -│ │ │ -│ │ ├─badger -│ │ │ HoneyBadgerEncrypt.java 加密实现类 -│ │ │ -│ │ ├─config -│ │ │ AESConfiguration.java AES配置 -│ │ │ EncryptAutoConfiguration.java -│ │ │ EncryptConfiguration.java -│ │ │ EncryptImportSelector.java -│ │ │ EncryptProvider.java -│ │ │ RSAConfiguration.java RSA配置 -│ │ │ -│ │ ├─cron -│ │ │ CronServer.java -│ │ │ -│ │ ├─enums -│ │ │ CipherMode.java 算法枚举 -│ │ │ Scenario.java 场景枚举 -│ │ │ -│ │ ├─generator -│ │ │ GeneratorSecretKey.java 密钥生成代理接口 -│ │ │ -│ │ ├─handler -│ │ │ ExecutorPostProcessor.java -│ │ │ ScenarioEncryptSchedule.java 场景调度 -│ │ │ ScenarioHandler.java 场景处理 -│ │ │ ScenarioHolder.java 核心容器 -│ │ │ ScenarioPostProcessor.java -│ │ │ ScenarioSchedule.java 场景调度实现类 -│ │ │ StorageScenario.java 存储场景 -│ │ │ TransmitScenario.java 传输场景 -│ │ │ -│ │ ├─register -│ │ │ RegisterBeanDefinition.java 注册密钥生成代理类 工厂模式 -│ │ │ -│ │ ├─spel -│ │ │ SpELExpressionHandler.java spel表达式处理类 -│ │ │ SpELParserContext.java -│ │ │ -│ │ └─util -│ │ EncryptUtils.java 工具类 +在 `pom.xml` 中添加以下依赖: +```xml + + cloud.longfa + encrypt-spring-boot-starter + 版本号 + ``` +请根据您的需求选择合适的版本号。 ## 使用说明 -1. 导入maven坐标 - - ```xml - - cloud.longfa - encrypt-spring-boot-starter - 1.0.5-RELEASE - - ``` - - - -## 配置说明 - -```yaml -badger: - encrypt: - #16字节 1byte = 8bit - aes-iv: 2404308462934f9f - #128/192/256 bits 16/24/32/ 字节 - aes-key: c4a98b23a8d94035bc9e0896b620b6a7 - public-key-base64: xxx #rsa加密算法公钥 - private-key-base64: xxx #rsa加密算法私钥 - sm4-key: xxxxxx #长度为16个字节 - sm4-iv: xxxxxxx #长度为16个字节 -``` - -## 注解参数说明 - -- > 在启动类上标注 **@EnableEncrypt** 注解 表示 启用加密模块 -- 加密注解:**@Encrypt** -- 解密注解:**@Decypt** -- 字段注解:**@Badger** +### 启用加密功能 -**加解密参数一样** - -1、scenario - -scenario值为枚举类型 - -```java -/** - * The enum Scenario. - * @author : longfa - * @email : longfa0130@gmail.com - * @description : 应用场景 网络接传输 、存储 - * @since : 1.0.0 - */ -public enum Scenario{ - /** - * Transmit scenario. - */ - transmit, //传输 - /** - * Storage scenario. - */ - storage, //存储 -} -``` - -2 cipher - -cipher值为枚举类型 - -```java -/** - * The enum Cipher mode. - * - * @author : longfa - * @email : longfa0130@gmail.com - * @description : 加密模式 - * @since : 1.0.0 - */ -public enum CipherMode { - /** - * Aes cipher mode. - */ - AES, - /** - * Rsa cipher mode. - */ - RSA, - /** - * Sm 4 cipher mode. - */ - SM4, - /** - * 混合加密 AES_RSA - */ - AES_RSA, - /** - *混合加密 SM4_RSA - */ - SM4_RSA, - /** - * 该值不能用于 @Encrypt @Decrypt注解 这用于 @Badger - * 如果为DEFAULT 则会使用@Encrypt 或者@Decrypt的加密模式 @Badger注解的默认值为DEFAULT - * 你可以切换成其他支持的属性 比如AES RSA SM4 或者 混合加密方式 - */ - DEFAULT, - -} -``` - -3 caseSensitive其值未做处理 所以不用设置 默认不区分大小写 - -4 fields - -fields 值为数组类型 加密的字段名(多个) - -```java - /** - * 加密的字段名方法加密需要指定字段名称 默认是对data字段解密 - * - * @return the string [ ] - */ - String[] fields() default {"data"}; - - - @RequestMapping("/efj") - @Decrypt(fields = {"password","card","address"},cipher = CipherMode.RSA,scenario = Scenario.transmit) - public Map> test1(@RequestBody Map> map){ - return map; - } - - Test类 - public class Test implements Cloneable{ - private String username; - private String password; - private String email; - private String phone; - private String address; - private String card; -``` - -5 value spel 表达式 已经经过加工 简单应用 @[beanName].[方法方法/常量名] - -```java -/** - * SpEL表达式 对SpEL表达式的支持 - * * @beanName.method or @beanName.field the field not be -> private decorated - * * @ss.abc() @ss.name - * - * @return the string - */ -String value() default ""; -``` - -6 dynamic 动态属性 - -使用规则 结合混合加密算法使用 否则不生效 - -```java -/** - * 动态密钥 支持混合算法 sm4-rsa aes-rsa {@CipherMode} - * @return the boolean - */ -boolean dynamic() default false; -``` - - - - - -## 使用教程 - -启动类上标注 @EnableEncrypt +在您的 Spring Boot 启动类上添加注解: ```java -@EnableEncrypt //启动该模块 不标注不生效!!! +@EnableEncrypt @SpringBootApplication -public class TestApplication { - public static void main(String[] args) { - SpringApplication.run(TestApplication.class, args); - } -} -``` - -### (一) 、传输场景案例 - -*非混合加密模式* - -#### 1.1 **简单易用法** - -*@Encrypt 安装字段进行加解密 属性: fields = {"username","password"} 不光是对字段名生效 参数也生效* AES加密 那么就用AES解密 - -实体类 - -```java -public class Test implements Cloneable{ - private String username; - private String password; - private String email; - private String phone; - private String address; -``` - -控制器 - - ```java -xxxController //控制器 - //传输加密 @ENC.SYSTEM_USER 同等 Fields.SYS_USER 同等 @ENC.custom() - @GetMapping("/aaa") - @Encrypt( fields = {"username","password"},cipher = CipherMode.AES,scenario = Scenario.transmit) - public Map> getTest1(){ - return queryData(); //模拟100条数据 -} - - private Map> queryData(){ - Map> stringListHashMap = new HashMap<>(); - Test testF = new Test(); - List testList = new ArrayList<>(); - for (int i = 0; i < 2; i++) { - Test test = testF.clone(); - test.setUsername("少林寺张三丰"+new Random().nextFloat()); - test.setPassword("密码8个8 你来破解啊"+ UUID.randomUUID()); - test.setAddress("xx省xx市xxx"); - test.setEmail("longfaxxxx@163.com"); - test.setPhone("18886137xxx"); - test.setCard("xxx6xx19xx01306xxx"); - testList.add(test); - } - stringListHashMap.put("data",testList); - return stringListHashMap; - } - ``` - -**如果解密呢???** - -xxx控制器 - -```java -//传输解密 -@PostMapping("/bbb") -@Decrypt(fields = {"username","password"},cipher = CipherMode.AES,scenario = Scenario.transmit) -public Map> test1(@RequestBody Map> map){ - return map; -} -``` - -#### 1.2 spel表达式 - -@Encrypt 注解属性:value = "@类名.方法" 跟fields属性一样 方法返回的必须是数组 也是返回待加密的字段 {"username","password"} - -```java - xxxController //控制器 - //传输加密 @ENC.SYSTEM_USER 同等 Fields.SYS_USER 同等 @ENC.custom() - //ta们最终返回的是数组 {"username","password"} 不用好奇 用了模板解析 - @GetMapping("/aaa") - @Encrypt(value ="@ENC.SYSTEM_USER",cipher = CipherMode.RSA,scenario = Scenario.transmit) - public Map> getTest1(){ - return queryData(); //模拟的数据 +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); } -``` - -#### 1.3 @Badger - -@Badger 标注在需要加密的字段上 - -属性只有一个: - -```java -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Badger { - /** - * 默认加密方式 AES算法加密 DEFAULT则会根据@Encrypt 或者@Decrypt cipher 的值 - * - * @return {@link CipherMode} - */ - CipherMode cipher() default CipherMode.DEFAULT; } ``` -​ 跟@Encrypt @Decrypt 上的一个属性一模一样 - -如果你修改了默认值CipherMode.DEFAULT 则会用@Badger注解上的为准 +### 加密注解使用 -**每一个字段每一种加密算法 会出现上面后果呢???** - -不用担心会导致多层加密 它会根据你选择的加密算法来加密该字段 - -实体类 - -```java -@Badger(cipher = CipherMode.SM4) -private String phone; -@Badger(cipher = CipherMode.RSA) -private String address; -``` - -控制器 +在需要加密的方法上使用 `@Encrypt` 注解: ```java -@GetMapping("/aaa") -@Encrypt(cipher = CipherMode.SM4,scenario = Scenario.transmit) -public Map> getTest1(){ - return queryData(); -} -``` +@RestController +public class DataController { -#### 1.4 每个字段每一种加密算法 - -```java -@Badger(cipher = CipherMode.AES) -private String email; -@Badger(cipher = CipherMode.SM4) -private String phone; -@Badger(cipher = CipherMode.RSA) -private String address; -``` - -#### 1.5 无敌模式 - -```java -//xxx控制器 -@GetMapping("/aaa") -@Encrypt(value =SPEL.SYS_USER,fileds={"username","password"},cipher = CipherMode.RSA,scenario = Scenario.transmit) -public Map> getTest1(){ - return queryData(); -} -``` - -```java -//xxx 实体类 -private String username; -private String password; -@Badger(cipher = CipherMode.AES) -private String email; -@Badger(cipher = CipherMode.SM4) -private String phone; -@Badger(cipher = CipherMode.RSA) -private String address; -``` - -放心 这种方式也是支持的!!!! - -#### 1.6 解密 - - -```java -//xxx控制器 -//传输解密 -@PostMapping("/bbb") -@Decrypt(value = SPEL.SYS_USER,cipher = CipherMode.SM4,scenario = Scenario.transmit) -public Map> test1(@RequestBody Map> map){ - return map; -} -// value 属性 就是类名.变量 前提是这个变量 类能访问得到 -@Component("ENC") -public class SPEL { - //1 系统用户 - public static final String SYS_USER = "@ENC.SYSTEM_USER"; - public static final String[] SYSTEM_USER = {"email","password"}; - -//xxx实体类 -private String username; -@Badger //默认 跟随上级 @Decrypt所指得加密算法 -private String password; -@Badger(cipher = CipherMode.AES) //这个字段用AES加密算法 -private String email; -@Badger(cipher = CipherMode.SM4) //这个字段用SM4加密算法 -private String phone; -@Badger(cipher = CipherMode.RSA) //这个字段用RSA加密算法 -private String address; -private String card; -``` - -### (二)、混合加密 - -#### 2.1 传输场景-混合加密 - -```java -//传输加密 模拟从service获取数据 @ENC.SYSTEM_USER 同等 Fields.SYS_USER 同等 @ENC.custom() 等同于使用@Badger该注解进行标识 -// 更推荐 "@ENC.SYSTEM_USER" @Badger 这种写法 支持任意的请求方式 支持多属性混合使用 value fields 注解同时使用 不仅仅是支持web容器 -//支持rpc远程调用加解密 @Badger 的值默认就是跟随@Encrypt的加密模式 你可以指定某一个字段用何种加密模式 可以混合使用 -//dynamic = true 则你的cipher参数必须也是支持动态密钥的 仅支持SM4-RSA AES-RSA 两种混合模式 -//dynamic = true 每一次的密钥都是变化的 你可以通过 HoneyBadgerEncrypt 实例获取变化后的密钥 推荐使用过滤器 -@GetMapping("/aaa") -@Encrypt(value =SPEL.SYS_USER,cipher = CipherMode.SM4_RSA,scenario = Scenario.transmit) -public Map> getTest1(){ - return queryData(); + @Encrypt(cipherMode = CipherMode.AES) + @GetMapping("/data") + public String getData() { + return "敏感数据"; + } } - -//实体类 -@Badger -private String username; -@Badger -private String password; -@Badger -private String email; ``` -*仅支持SM4-RSA AES-RSA 两种混合模式* - -RSA加密AES 或者是SM4的密钥 +### 解密注解使用 -获取RSA加密后的AES 、SM4密钥 +在需要解密的方法上使用 `@Decrypt` 注解: ```java -/** - * @author : longfa - * @email : longfa0130@gmail.com - * @description : 案例 - * @since : 1.0.0 - */ -@ControllerAdvice -public class ResponseAdvice implements ResponseBodyAdvice { - public static String AESKEY = "AES-RSA"; - public static String SM4KEY = "SM4-RSA"; - - @Override - public boolean supports(MethodParameter returnType, Class converterType) { - return true; - } +@RestController +public class DataController { - @Nullable - @Override - public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { - // 拿到密钥 设置到响应头 前端获取 通过RSA解密获取AES密钥 再通过AES解密器对密文解密 - response.getHeaders().set(AESKEY, HoneyBadgerEncrypt.getAesKeyRSACiphertext()); - //拿到密钥 设置到响应头 前端获取 通过RSA解密获取SM4密钥 再通过SM4解密器对密文解密 - response.getHeaders().set(SM4KEY,HoneyBadgerEncrypt.getSm4KeyRSACiphertext()); - return body; + @Decrypt(cipherMode = CipherMode.AES) + @PostMapping("/decrypt-data") + public String receiveData(@RequestBody String encryptedData) { + return "已解密数据: " + encryptedData; } } - ``` -#### 2.2 前端传过来的密钥怎么接收??? +### 存储场景加密解密 -*不是随机密钥 自然不用去配置!!!!* - -做个判断即可 +使用 `@Badger` 注解对数据存储字段进行加密处理: ```java -/** - * @author : longfa - * @email : longfa0130@gmail.com - * @description : 案例 - * @since : 1.0.0 - */ -@Component -public class xxxxxxxxx extends OncePerRequestFilter { - public static String AESKEY = "AES-RSA"; - public static String SM4KEY = "SM4-RSA"; - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - String aesKey = request.getHeader(AESKEY); - String sm4Key = request.getHeader(SM4KEY); - if (StringUtils.hasText(aesKey)){ //判断一 四行代码 花不了多少时间 复制粘贴就行了 异常处理还没有做!!! - HoneyBadgerEncrypt.setRSACiphertextForAESKey(aesKey); - } - if (StringUtils.hasText(sm4Key)){ //判断二 - HoneyBadgerEncrypt.setRSACiphertextForSM4Key(sm4Key); - } - filterChain.doFilter(request,response); - } +public class User { + @Badger(cipherMode = CipherMode.SM4) + private String password; } ``` -*基本上复制粘贴就完工了!!!* +### 混合加密模式 -#### 2.2 混合解密之随机密钥 +支持动态密钥结合 RSA 和对称加密进行混合加密传输,确保数据传输的高安全性。 -跟上面一样 区别在于 密钥会动态生成 dynamic 属性设置为true就行了 +## 配置说明 -```java -@GetMapping("/aaa") -@Encrypt(value =SPEL.SYS_USER,cipher = CipherMode.SM4_RSA,scenario = Scenario.transmit,dynamic = true) -public Map> getTest1(){ - return queryData(); -} +在 `application.yml` 中配置加密参数: + +```yaml +encrypt: + badger: + aes-key: your-aes-key + aes-iv: your-aes-iv + sm4-key: your-sm4-key + sm4-iv: your-sm4-iv + private-key: your-private-key + public-key: your-public-key ``` +## 支持的加密模式 +| 加密算法 | 模式说明 | +|----------|----------| +| AES | 对称加密,适合快速加密/解密 | +| SM4 | 国密算法,适用于符合中国标准的加密需求 | +| RSA | 非对称加密,适合密钥交换和数字签名 | +| SM3 | 哈希算法,用于数据摘要处理 | -### (三) 存储场景案例 - -传输场景你会了 那么存储场景就是so easy!!! 设置 scenario = Scenario.storage - - ```java - - xxxController //控制器 - //传输加密 @ENC.SYSTEM_USER 同等 Fields.SYS_USER 同等 @ENC.custom() 你用注解标注字段可以 怎么方便怎么用 - @GetMapping("/aaa") - @Encrypt(value ="@ENC.SYSTEM_USER",cipher = CipherMode.RSA,scenario = Scenario.storage) - public Map> getTest1(){ - return queryData(); //模拟的数据 - } - //传输解密 - @PostMapping("/bbb") - @Decrypt(value = SPEL.SYS_USER,cipher = CipherMode.RSA,scenario = Scenario.transmit) - public Map> test1(@RequestBody Map> map){ - return map; - } - - - //类名ENC 配合spel表达式使用 更方便 - // 比如 value= "@ENC.SYSTEM_USER" 经过加密框架解析后的值: {"address","username","email","password"} - // 同上来讲就是方法调用 你可以写成 类名.常量 类名.方法 - @Component("ENC") - public class SPEL { - //1 系统用户 - public static final String SYS_USER = "@ENC.SYSTEM_USER"; - //1 待加密字段 地址、用户名、邮箱、密码 - public static final String[] SYSTEM_USER = {"address","username","email","password"}; - - //1 - public String[] custom(){ - return new String[]{"address","username","email"}; - } - - } - - //测试类 service层 模拟存储至数据库 从数据库取出数据 的加解密过程 - @Service("testService") - public class TestService { - - //or value = "@ENCRYPT.ADMIN_USER", 同等 Fields.ADM_USER - @Encrypt(value = SPEL.ADM_USER,cipher = CipherMode.AES,scenario = Scenario.storage) - @Decrypt(value = "@ENC.ADMIN_USER",cipher = CipherMode.AES,scenario = Scenario.storage) - public List testList(List testList, HttpServletRequest request, HttpServletResponse response){ - System.out.println(testList+"\n加密了"); - return testList; - } - } - ``` - +## 优势 +- **简单易用**:基于注解和配置实现,开发者无需深入实现细节。 +- **性能优秀**:使用线程池优化加密任务调度,支持高并发。 +- **可扩展性强**:支持多种加密算法和混合模式,满足不同业务需求。 ## 参与贡献 -写的潦草 您有好的想法或者意见 欢迎提出来 一同完善!!! +欢迎贡献代码和提出改进建议。提交 PR 前请确保代码风格与现有代码一致,并添加必要的测试用例。 -## 性能 +## 许可证 -cpu:轻薄本 i7 8550u +该项目基于 [MIT License](LICENSE) 开源,请在项目中尊重并保留相关许可声明。 -混合加密 8万条数据 耗时 2.5秒左右 解密 1.8秒 没有出现栈内存溢出这种极端的情况 +## 性能 -作者:longfa email:longfa0130@163.com || longfa0130@gmail.com \ No newline at end of file +框架经过优化,适用于中小型项目的数据加密处理,具备良好的并发性能。对于大规模数据处理,建议结合异步加密策略进行使用。 \ No newline at end of file