<dependency>
<groupId>cloud.longfa</groupId>
<artifactId>encrypt-spring-boot-starter</artifactId>
<version>1.0.6-RELEASE</version>
</dependency>
WEB应用加解密请查看此根目录WEBAPP.md文档 配套使用
aop、反射机制、递归算法 、策略模式
- 全注解、支持spel表达式(改造过,易用)、支持任意字段、任意参数、任意请求方式
- 支持多种场景(传输场景、存储场景)
- 支持扩展其他场景(已经实现网络传输、存储加解密)
- 支持扩展其他的加密算法
- 支持的加密模式:单类算法加密(多参数单算法)、多类算法混合(单参数|字段单算法)、混合模式(单参数 多种算法)、混合模式之随机密钥
- 支持任意请求方式 、任意多个参数、body 支持java集合、实体类等等
- 支持RPC框架 实现前端后、端对端数据加密
- 支持任意多个字段|参数 任意多种加密算法同时用
网络传输后端加减密 前端加解密没空写
支持RPC框架 远程调用 多种算法混合使用 能控制到每一个字段 都使用独立的算法 不必担心解不了密!!! 怎么加怎么解
支持存储加解密 多种算法混合使用
任意请求方式 不仅仅只是争对body 也支持请求参数(任意个)
无限层 支持无限套娃!!!
比如集合嵌套集合 支持多层级嵌套
支持的加密算法 AES、RSA、SM4 混合加密 动态密钥混合加密 同时也支持扩展其他算法
-
单模式加密:
一个接口只使用一种加密算法
-
多种算法单模式
一个接口下每一个参数使用单独的加密算法
-
混合加密:
两种以上的加密算法融合使用 密钥使用自己配置的
-
动态混合加密:
密钥是随机生成 每一次请求密钥都是不一样 提供了外部获取密钥的方式
老版本:
├─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 工具类
-
导入maven坐标
<dependency> <groupId>cloud.longfa</groupId> <artifactId>encrypt-spring-boot-starter</artifactId> <version>1.0.5-RELEASE</version> </dependency>
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值为枚举类型
/**
* 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值为枚举类型
/**
* 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 值为数组类型 加密的字段名(多个)
/**
* 加密的字段名方法加密需要指定字段名称 默认是对data字段解密
*
* @return the string [ ]
*/
String[] fields() default {"data"};
@RequestMapping("/efj")
@Decrypt(fields = {"password","card","address"},cipher = CipherMode.RSA,scenario = Scenario.transmit)
public Map<String,List<Test>> test1(@RequestBody Map<String,List<Test>> 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].[方法方法/常量名]
/**
* 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 动态属性
使用规则 结合混合加密算法使用 否则不生效
/**
* 动态密钥 支持混合算法 sm4-rsa aes-rsa {@CipherMode}
* @return the boolean
*/
boolean dynamic() default false;
启动类上标注 @EnableEncrypt
@EnableEncrypt //启动该模块 不标注不生效!!!
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
非混合加密模式
@Encrypt 安装字段进行加解密 属性: fields = {"username","password"} 不光是对字段名生效 参数也生效 AES加密 那么就用AES解密
实体类
public class Test implements Cloneable{
private String username;
private String password;
private String email;
private String phone;
private String address;
控制器
xxxController //控制器
//传输加密 @ENC.SYSTEM_USER 同等 Fields.SYS_USER 同等 @ENC.custom()
@GetMapping("/aaa")
@Encrypt( fields = {"username","password"},cipher = CipherMode.AES,scenario = Scenario.transmit)
public Map<String,List<Test>> getTest1(){
return queryData(); //模拟100条数据
}
private Map<String,List<Test>> queryData(){
Map<String,List<Test>> stringListHashMap = new HashMap<>();
Test testF = new Test();
List<Test> 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控制器
//传输解密
@PostMapping("/bbb")
@Decrypt(fields = {"username","password"},cipher = CipherMode.AES,scenario = Scenario.transmit)
public Map<String,List<Test>> test1(@RequestBody Map<String,List<Test>> map){
return map;
}
@Encrypt 注解属性:value = "@类名.方法" 跟fields属性一样 方法返回的必须是数组 也是返回待加密的字段 {"username","password"}
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<String,List<Test>> getTest1(){
return queryData(); //模拟的数据
}
@Badger 标注在需要加密的字段上
属性只有一个:
@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注解上的为准
每一个字段每一种加密算法 会出现上面后果呢???
不用担心会导致多层加密 它会根据你选择的加密算法来加密该字段
实体类
@Badger(cipher = CipherMode.SM4)
private String phone;
@Badger(cipher = CipherMode.RSA)
private String address;
控制器
@GetMapping("/aaa")
@Encrypt(cipher = CipherMode.SM4,scenario = Scenario.transmit)
public Map<String,List<Test>> getTest1(){
return queryData();
}
@Badger(cipher = CipherMode.AES)
private String email;
@Badger(cipher = CipherMode.SM4)
private String phone;
@Badger(cipher = CipherMode.RSA)
private String address;
//xxx控制器
@GetMapping("/aaa")
@Encrypt(value =SPEL.SYS_USER,fileds={"username","password"},cipher = CipherMode.RSA,scenario = Scenario.transmit)
public Map<String,List<Test>> getTest1(){
return queryData();
}
//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;
放心 这种方式也是支持的!!!!
//xxx控制器
//传输解密
@PostMapping("/bbb")
@Decrypt(value = SPEL.SYS_USER,cipher = CipherMode.SM4,scenario = Scenario.transmit)
public Map<String,List<Test>> test1(@RequestBody Map<String,List<Test>> 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;
//传输加密 模拟从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<String,List<Test>> getTest1(){
return queryData();
}
//实体类
@Badger
private String username;
@Badger
private String password;
@Badger
private String email;
仅支持SM4-RSA AES-RSA 两种混合模式
RSA加密AES 或者是SM4的密钥
获取RSA加密后的AES 、SM4密钥
/**
* @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;
}
@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;
}
}
不是随机密钥 自然不用去配置!!!!
做个判断即可
/**
* @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);
}
}
基本上复制粘贴就完工了!!!
跟上面一样 区别在于 密钥会动态生成 dynamic 属性设置为true就行了
@GetMapping("/aaa")
@Encrypt(value =SPEL.SYS_USER,cipher = CipherMode.SM4_RSA,scenario = Scenario.transmit,dynamic = true)
public Map<String,List<Test>> getTest1(){
return queryData();
}
传输场景你会了 那么存储场景就是so easy!!! 设置 scenario = Scenario.storage
xxxController //控制器
//传输加密 @ENC.SYSTEM_USER 同等 Fields.SYS_USER 同等 @ENC.custom() 你用注解标注字段可以 怎么方便怎么用
@GetMapping("/aaa")
@Encrypt(value ="@ENC.SYSTEM_USER",cipher = CipherMode.RSA,scenario = Scenario.storage)
public Map<String,List<Test>> getTest1(){
return queryData(); //模拟的数据
}
//传输解密
@PostMapping("/bbb")
@Decrypt(value = SPEL.SYS_USER,cipher = CipherMode.RSA,scenario = Scenario.transmit)
public Map<String,List<Test>> test1(@RequestBody Map<String,List<Test>> 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<Test> testList(List<Test> testList, HttpServletRequest request, HttpServletResponse response){
System.out.println(testList+"\n加密了");
return testList;
}
}
写的潦草 您有好的想法或者意见 欢迎提出来 一同完善!!!
cpu:轻薄本 i7 8550u
混合加密 8万条数据 耗时 2.5秒左右 解密 1.8秒 没有出现栈内存溢出这种极端的情况
作者:longfa email:longfa0130@163.com || longfa0130@gmail.com