├── .gitignore ├── src └── main │ └── java │ └── com │ └── barcke │ └── y │ └── rsa │ ├── annotation │ ├── Encrypt.java │ ├── Decrypt.java │ └── EnableSecurity.java │ ├── exception │ └── EncryptRequestException.java │ ├── pojo │ └── KeyInfo.java │ ├── util │ ├── Base64Util.java │ ├── JsonUtils.java │ └── RSAUtil.java │ ├── config │ └── SecretKeyConfig.java │ └── advice │ ├── EncryptRequestBodyAdvice.java │ ├── EncryptResponseBodyAdvice.java │ └── DecryptHttpInputMessage.java ├── README.md └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/test/** 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | *.log 21 | *.lck 22 | /test/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/annotation/Encrypt.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * ,;,,; 7 | * ,;;'( 社 8 | * __ ,;;' ' \ 会 9 | * /' '\'~~'~' \ /'\.) 主 10 | * ,;( ) / |. 义 11 | *,;' \ /-.,,( ) \ 码 12 | * ) / ) / )| 农 13 | * || || \) 14 | * (_\ (_\ 15 | * 16 | * @author Barcke 17 | * @version 1.0 18 | **/ 19 | @Target(ElementType.METHOD) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Documented 22 | public @interface Encrypt{ 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/exception/EncryptRequestException.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.exception; 2 | 3 | /** 4 | * ,;,,; 5 | * ,;;'( 社 6 | * __ ,;;' ' \ 会 7 | * /' '\'~~'~' \ /'\.) 主 8 | * ,;( ) / |. 义 9 | *,;' \ /-.,,( ) \ 码 10 | * ) / ) / )| 农 11 | * || || \) 12 | * (_\ (_\ 13 | * 14 | * @author Barcke 15 | * @version 1.0 16 | **/ 17 | public class EncryptRequestException extends RuntimeException { 18 | 19 | public EncryptRequestException(String msg) { 20 | super(msg); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/pojo/KeyInfo.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.pojo; 2 | 3 | /** 4 | * ,;,,; 5 | * ,;;'( 社 6 | * __ ,;;' ' \ 会 7 | * /' '\'~~'~' \ /'\.) 主 8 | * ,;( ) / |. 义 9 | *,;' \ /-.,,( ) \ 码 10 | * ) / ) / )| 农 11 | * || || \) 12 | * (_\ (_\ 13 | * 14 | * @author Barcke 15 | * @version 1.0 16 | **/ 17 | public class KeyInfo { 18 | public String getPrivateKey() { 19 | return privateKey; 20 | } 21 | 22 | public void setPrivateKey(String privateKey) { 23 | this.privateKey = privateKey; 24 | } 25 | 26 | public String getPublicKey() { 27 | return publicKey; 28 | } 29 | 30 | public void setPublicKey(String publicKey) { 31 | this.publicKey = publicKey; 32 | } 33 | 34 | private String privateKey; 35 | private String publicKey; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/annotation/Decrypt.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.annotation; 2 | 3 | import com.barcke.y.rsa.exception.EncryptRequestException; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * ,;,,; 9 | * ,;;'( 社 10 | * __ ,;;' ' \ 会 11 | * /' '\'~~'~' \ /'\.) 主 12 | * ,;( ) / |. 义 13 | *,;' \ /-.,,( ) \ 码 14 | * ) / ) / )| 农 15 | * || || \) 16 | * (_\ (_\ 17 | * 18 | * @author Barcke 19 | * @version 1.0 20 | **/ 21 | @Target(ElementType.METHOD) 22 | @Retention(RetentionPolicy.RUNTIME) 23 | @Documented 24 | public @interface Decrypt{ 25 | 26 | /** 27 | * 请求参数一定要是加密内容 28 | * @return boolean 29 | */ 30 | boolean required() default false; 31 | 32 | /** 33 | * 请求数据时间戳校验时间差 34 | * 超过(当前时间-指定时间)的数据认定为伪造 35 | * 注意应用程序需要捕获 {@link EncryptRequestException} 异常 36 | * @return long 37 | */ 38 | long timeout() default 3000; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/annotation/EnableSecurity.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.annotation; 2 | 3 | import com.barcke.y.rsa.advice.EncryptRequestBodyAdvice; 4 | import com.barcke.y.rsa.advice.EncryptResponseBodyAdvice; 5 | import com.barcke.y.rsa.config.SecretKeyConfig; 6 | import org.springframework.context.annotation.Import; 7 | 8 | import java.lang.annotation.*; 9 | 10 | /** 11 | * ,;,,; 12 | * ,;;'( 社 13 | * __ ,;;' ' \ 会 14 | * /' '\'~~'~' \ /'\.) 主 15 | * ,;( ) / |. 义 16 | *,;' \ /-.,,( ) \ 码 17 | * ) / ) / )| 农 18 | * || || \) 19 | * (_\ (_\ 20 | * 21 | * @author Barcke 22 | * @version 1.0 23 | **/ 24 | @Target({ElementType.TYPE}) 25 | @Retention(RetentionPolicy.RUNTIME) 26 | @Inherited 27 | @Documented 28 | @Import({SecretKeyConfig.class, 29 | EncryptResponseBodyAdvice.class, 30 | EncryptRequestBodyAdvice.class}) 31 | public @interface EnableSecurity{ 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/util/Base64Util.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.util; 2 | 3 | import org.apache.commons.codec.binary.Base64; 4 | 5 | /** 6 | * ,;,,; 7 | * ,;;'( 社 8 | * __ ,;;' ' \ 会 9 | * /' '\'~~'~' \ /'\.) 主 10 | * ,;( ) / |. 义 11 | *,;' \ /-.,,( ) \ 码 12 | * ) / ) / )| 农 13 | * || || \) 14 | * (_\ (_\ 15 | * 16 | * @author Barcke 17 | * @version 1.0 18 | **/ 19 | public class Base64Util{ 20 | 21 | /** 22 | * Decoding to binary 23 | * @param base64 base64 24 | * @return byte 25 | * @throws Exception Exception 26 | */ 27 | public static byte[] decode(String base64) throws Exception { 28 | return Base64.decodeBase64(base64); 29 | } 30 | 31 | /** 32 | * Binary encoding as a string 33 | * @param bytes byte 34 | * @return String 35 | * @throws Exception Exception 36 | */ 37 | public static String encode(byte[] bytes) throws Exception { 38 | return new String(Base64.encodeBase64(bytes) , "UTF-8"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/util/JsonUtils.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.util; 2 | 3 | 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.JsonNode; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * ,;,,; 12 | * ,;;'( 社 13 | * __ ,;;' ' \ 会 14 | * /' '\'~~'~' \ /'\.) 主 15 | * ,;( ) / |. 义 16 | *,;' \ /-.,,( ) \ 码 17 | * ) / ) / )| 农 18 | * || || \) 19 | * (_\ (_\ 20 | * 21 | * @author Barcke 22 | * @version 1.0 23 | **/ 24 | public class JsonUtils { 25 | 26 | private JsonUtils() { 27 | } 28 | 29 | private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); 30 | 31 | public static JsonNode getNode(String content, String key) throws IOException { 32 | JsonNode jsonNode = OBJECT_MAPPER.readTree(content); 33 | return jsonNode.get(key); 34 | } 35 | 36 | public static String writeValueAsString(Object body) throws JsonProcessingException { 37 | return OBJECT_MAPPER.writeValueAsString(body); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/config/SecretKeyConfig.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | /** 7 | * ,;,,; 8 | * ,;;'( 社 9 | * __ ,;;' ' \ 会 10 | * /' '\'~~'~' \ /'\.) 主 11 | * ,;( ) / |. 义 12 | *,;' \ /-.,,( ) \ 码 13 | * ) / ) / )| 农 14 | * || || \) 15 | * (_\ (_\ 16 | * 17 | * @author Barcke 18 | * @version 1.0 19 | **/ 20 | @ConfigurationProperties(prefix = "rsa.encrypt") 21 | @Configuration 22 | public class SecretKeyConfig { 23 | 24 | private String privateKey; 25 | 26 | private String publicKey; 27 | 28 | private String charset = "UTF-8"; 29 | 30 | private boolean open = true; 31 | 32 | private boolean showLog = false; 33 | 34 | /** 35 | * 请求数据时间戳校验时间差 36 | * 超过指定时间的数据认定为伪造 37 | */ 38 | private boolean timestampCheck = false; 39 | 40 | public String getPrivateKey() { 41 | return privateKey; 42 | } 43 | 44 | public void setPrivateKey(String privateKey) { 45 | this.privateKey = privateKey; 46 | } 47 | 48 | public String getPublicKey() { 49 | return publicKey; 50 | } 51 | 52 | public void setPublicKey(String publicKey) { 53 | this.publicKey = publicKey; 54 | } 55 | 56 | public String getCharset() { 57 | return charset; 58 | } 59 | 60 | public void setCharset(String charset) { 61 | this.charset = charset; 62 | } 63 | 64 | public boolean isOpen() { 65 | return open; 66 | } 67 | 68 | public void setOpen(boolean open) { 69 | this.open = open; 70 | } 71 | 72 | public boolean isShowLog() { 73 | return showLog; 74 | } 75 | 76 | public void setShowLog(boolean showLog) { 77 | this.showLog = showLog; 78 | } 79 | 80 | public boolean isTimestampCheck() { 81 | return timestampCheck; 82 | } 83 | 84 | public void setTimestampCheck(boolean timestampCheck) { 85 | this.timestampCheck = timestampCheck; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rsa-body-spring-boot 2 | ## 使用方式 3 | 导入对应的MAVEN包: 4 | 5 | ``` 6 | 7 | com.barcke.y 8 | rsa-body-spring-boot 9 | 1.0.0 10 | 11 | ``` 12 | 导入对应的包后开启配置项: 13 | ``` 14 | rsa: 15 | encrypt: 16 | open: true # 是否开启加密 true or false 17 | showLog: true # 是否打印加解密log true or false 默认false 18 | timestampCheck: true #是否开启时间校验 默认false 19 | publicKey: #公钥信息 20 | privateKey: #私钥信息 21 | ``` 22 | 可以使用如下方法生产公私钥: 23 | ``` 24 | import com.barcke.y.rsa.util.RSAUtil 25 | 26 | //用于生产公私钥 返回值为对应的公私钥信息 生成后请保管好 27 | RSAUtil.genKeyPair(); 28 | ``` 29 | 30 | 开启配置项后在项目中使用注解: 31 | ``` 32 | @Encrypt //加密 33 | @Decrypt(required = true, timeout = 30000L) //解密 required默认关闭,timeout超时时间设置 34 | ``` 35 | 示例: 36 | ![](https://imgkr.cn-bj.ufileos.com/11593bc0-ef37-403a-85d5-0e8a9d80d07a.png) 37 | **注意传参方式为“application/json”加密会对整个回参加密,解密会对整个入参解密.** 38 | 39 | 前端加解密可以同步公私钥信息、不过需要注意RSA的长度加密为117解密为256超长是会报错的~ 40 | 前端加解密可参考如下: 41 | ``` 42 | 43 | 44 | 45 | 46 | 使用jsencrypt执行OpenSSL的RSA加密,解密 47 | 48 | 49 | 50 | 73 | 74 | 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/advice/EncryptRequestBodyAdvice.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.advice; 2 | 3 | import com.barcke.y.rsa.annotation.Decrypt; 4 | import com.barcke.y.rsa.config.SecretKeyConfig; 5 | import com.barcke.y.rsa.exception.EncryptRequestException; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.core.MethodParameter; 10 | import org.springframework.http.HttpInputMessage; 11 | import org.springframework.http.converter.HttpMessageConverter; 12 | import org.springframework.web.bind.annotation.ControllerAdvice; 13 | import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; 14 | 15 | import java.lang.reflect.Method; 16 | import java.lang.reflect.Type; 17 | import java.util.Objects; 18 | 19 | /** 20 | * ,;,,; 21 | * ,;;'( 社 22 | * __ ,;;' ' \ 会 23 | * /' '\'~~'~' \ /'\.) 主 24 | * ,;( ) / |. 义 25 | *,;' \ /-.,,( ) \ 码 26 | * ) / ) / )| 农 27 | * || || \) 28 | * (_\ (_\ 29 | * 30 | * @author Barcke 31 | * @version 1.0 32 | **/ 33 | @ControllerAdvice 34 | public class EncryptRequestBodyAdvice implements RequestBodyAdvice { 35 | 36 | private Logger log = LoggerFactory.getLogger(this.getClass()); 37 | 38 | private boolean encrypt; 39 | private Decrypt decryptAnnotation; 40 | 41 | @Autowired 42 | private SecretKeyConfig secretKeyConfig; 43 | 44 | @Override 45 | public boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) { 46 | Method method = methodParameter.getMethod(); 47 | if (Objects.isNull(method)) { 48 | encrypt = false; 49 | return false; 50 | } 51 | if (method.isAnnotationPresent(Decrypt.class) && secretKeyConfig.isOpen()) { 52 | encrypt = true; 53 | decryptAnnotation = methodParameter.getMethodAnnotation(Decrypt.class); 54 | return true; 55 | } 56 | // 此处如果按照原逻辑直接返回encrypt, 会造成一次修改为true之后, 后续请求都会变成true, 在不支持时, 需要做修正 57 | encrypt = false; 58 | return false; 59 | } 60 | 61 | @Override 62 | public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { 63 | return body; 64 | } 65 | 66 | @Override 67 | public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, 68 | Class> converterType){ 69 | if (encrypt) { 70 | try { 71 | return new DecryptHttpInputMessage(inputMessage, secretKeyConfig, decryptAnnotation); 72 | } catch (EncryptRequestException e) { 73 | throw e; 74 | } catch (Exception e) { 75 | log.error("Decryption failed", e); 76 | } 77 | } 78 | return inputMessage; 79 | } 80 | 81 | @Override 82 | public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, 83 | Class> converterType) { 84 | return body; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/advice/EncryptResponseBodyAdvice.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.advice; 2 | 3 | import com.barcke.y.rsa.annotation.Encrypt; 4 | import com.barcke.y.rsa.config.SecretKeyConfig; 5 | import com.barcke.y.rsa.util.Base64Util; 6 | import com.barcke.y.rsa.util.JsonUtils; 7 | import com.barcke.y.rsa.util.RSAUtil; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.core.MethodParameter; 12 | import org.springframework.http.MediaType; 13 | import org.springframework.http.converter.HttpMessageConverter; 14 | import org.springframework.http.server.ServerHttpRequest; 15 | import org.springframework.http.server.ServerHttpResponse; 16 | import org.springframework.util.StringUtils; 17 | import org.springframework.web.bind.annotation.ControllerAdvice; 18 | import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; 19 | 20 | import java.lang.reflect.Method; 21 | import java.util.Objects; 22 | 23 | /** 24 | * ,;,,; 25 | * ,;;'( 社 26 | * __ ,;;' ' \ 会 27 | * /' '\'~~'~' \ /'\.) 主 28 | * ,;( ) / |. 义 29 | *,;' \ /-.,,( ) \ 码 30 | * ) / ) / )| 农 31 | * || || \) 32 | * (_\ (_\ 33 | * 34 | * @author Barcke 35 | * @version 1.0 36 | **/ 37 | @ControllerAdvice 38 | public class EncryptResponseBodyAdvice implements ResponseBodyAdvice { 39 | 40 | private Logger log = LoggerFactory.getLogger(this.getClass()); 41 | 42 | private boolean encrypt; 43 | 44 | @Autowired 45 | private SecretKeyConfig secretKeyConfig; 46 | 47 | private static ThreadLocal encryptLocal = new ThreadLocal<>(); 48 | 49 | @Override 50 | public boolean supports(MethodParameter returnType, Class> converterType) { 51 | Method method = returnType.getMethod(); 52 | if (Objects.isNull(method)) { 53 | return encrypt; 54 | } 55 | encrypt = method.isAnnotationPresent(Encrypt.class) && secretKeyConfig.isOpen(); 56 | return encrypt; 57 | } 58 | 59 | @Override 60 | public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, 61 | Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { 62 | // EncryptResponseBodyAdvice.setEncryptStatus(false); 63 | // Dynamic Settings Not Encrypted 64 | Boolean status = encryptLocal.get(); 65 | if (null != status && !status) { 66 | encryptLocal.remove(); 67 | return body; 68 | } 69 | if (encrypt) { 70 | String publicKey = secretKeyConfig.getPublicKey(); 71 | try { 72 | String content = JsonUtils.writeValueAsString(body); 73 | if (!StringUtils.hasText(publicKey)) { 74 | throw new NullPointerException("Please configure rsa.encrypt.privatekeyc parameter!"); 75 | } 76 | byte[] data = content.getBytes("UTF-8"); 77 | byte[] encodedData = RSAUtil.encrypt(data, publicKey); 78 | String result = Base64Util.encode(encodedData); 79 | if(secretKeyConfig.isShowLog()) { 80 | log.info("Pre-encrypted data:{},After encryption:{}", content, result); 81 | } 82 | return result; 83 | } catch (Exception e) { 84 | log.error("Encrypted data exception", e); 85 | } 86 | } 87 | 88 | return body; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/advice/DecryptHttpInputMessage.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.advice; 2 | 3 | import com.barcke.y.rsa.annotation.Decrypt; 4 | import com.barcke.y.rsa.config.SecretKeyConfig; 5 | import com.barcke.y.rsa.exception.EncryptRequestException; 6 | import com.barcke.y.rsa.util.Base64Util; 7 | import com.barcke.y.rsa.util.JsonUtils; 8 | import com.barcke.y.rsa.util.RSAUtil; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.http.HttpHeaders; 13 | import org.springframework.http.HttpInputMessage; 14 | 15 | import java.io.BufferedReader; 16 | import java.io.ByteArrayInputStream; 17 | import java.io.InputStream; 18 | import java.io.InputStreamReader; 19 | import java.util.stream.Collectors; 20 | 21 | /** 22 | * ,;,,; 23 | * ,;;'( 社 24 | * __ ,;;' ' \ 会 25 | * /' '\'~~'~' \ /'\.) 主 26 | * ,;( ) / |. 义 27 | *,;' \ /-.,,( ) \ 码 28 | * ) / ) / )| 农 29 | * || || \) 30 | * (_\ (_\ 31 | * 32 | * @author Barcke 33 | * @version 1.0 34 | **/ 35 | public class DecryptHttpInputMessage implements HttpInputMessage { 36 | 37 | private Logger log = LoggerFactory.getLogger(this.getClass()); 38 | private HttpHeaders headers; 39 | private InputStream body; 40 | 41 | 42 | public DecryptHttpInputMessage(HttpInputMessage inputMessage, SecretKeyConfig secretKeyConfig, Decrypt decrypt) throws Exception { 43 | 44 | String privateKey = secretKeyConfig.getPrivateKey(); 45 | String charset = secretKeyConfig.getCharset(); 46 | boolean showLog = secretKeyConfig.isShowLog(); 47 | boolean timestampCheck = secretKeyConfig.isTimestampCheck(); 48 | 49 | if (StringUtils.isEmpty(privateKey)) { 50 | throw new IllegalArgumentException("privateKey is null"); 51 | } 52 | 53 | this.headers = inputMessage.getHeaders(); 54 | String content = new BufferedReader(new InputStreamReader(inputMessage.getBody())) 55 | .lines().collect(Collectors.joining(System.lineSeparator())); 56 | String decryptBody; 57 | // 未加密内容 58 | if (content.startsWith("{")) { 59 | // 必须加密 60 | if (decrypt.required()) { 61 | log.error("not support unencrypted content:{}", content); 62 | throw new EncryptRequestException("not support unencrypted content"); 63 | } 64 | log.info("Unencrypted without decryption:{}", content); 65 | decryptBody = content; 66 | } else { 67 | StringBuilder json = new StringBuilder(); 68 | content = content.replaceAll(" ", "+"); 69 | 70 | if (!StringUtils.isEmpty(content)) { 71 | String[] contents = content.split("\\|"); 72 | for (String value : contents) { 73 | value = new String(RSAUtil.decrypt(Base64Util.decode(value), privateKey), charset); 74 | json.append(value); 75 | } 76 | } 77 | decryptBody = json.toString(); 78 | if(showLog) { 79 | log.info("Encrypted data received:{},After decryption:{}", content, decryptBody); 80 | } 81 | } 82 | 83 | // 开启时间戳检查 84 | if (timestampCheck) { 85 | // 容忍最小请求时间 86 | long toleranceTime = System.currentTimeMillis() - decrypt.timeout(); 87 | long requestTime = JsonUtils.getNode(decryptBody, "timestamp").asLong(); 88 | // 如果请求时间小于最小容忍请求时间, 判定为超时 89 | if (requestTime < toleranceTime) { 90 | log.error("Encryption request has timed out, toleranceTime:{}, requestTime:{}, After decryption:{}", toleranceTime, requestTime, decryptBody); 91 | throw new EncryptRequestException("request timeout"); 92 | } 93 | } 94 | 95 | this.body = new ByteArrayInputStream(decryptBody.getBytes()); 96 | } 97 | 98 | @Override 99 | public InputStream getBody(){ 100 | return body; 101 | } 102 | 103 | @Override 104 | public HttpHeaders getHeaders() { 105 | return headers; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/barcke/y/rsa/util/RSAUtil.java: -------------------------------------------------------------------------------- 1 | package com.barcke.y.rsa.util; 2 | 3 | import com.barcke.y.rsa.pojo.KeyInfo; 4 | import org.apache.commons.codec.binary.Base64; 5 | 6 | import javax.crypto.Cipher; 7 | import java.io.ByteArrayOutputStream; 8 | import java.security.*; 9 | import java.security.interfaces.RSAPrivateKey; 10 | import java.security.interfaces.RSAPublicKey; 11 | import java.security.spec.PKCS8EncodedKeySpec; 12 | import java.security.spec.X509EncodedKeySpec; 13 | 14 | /** 15 | * ,;,,; 16 | * ,;;'( 社 17 | * __ ,;;' ' \ 会 18 | * /' '\'~~'~' \ /'\.) 主 19 | * ,;( ) / |. 义 20 | *,;' \ /-.,,( ) \ 码 21 | * ) / ) / )| 农 22 | * || || \) 23 | * (_\ (_\ 24 | * 25 | * @author Barcke 26 | * @version 1.0 27 | **/ 28 | public class RSAUtil{ 29 | 30 | /** 31 | * encryption algorithm RSA 32 | */ 33 | public static final String KEY_ALGORITHM = "RSA"; 34 | 35 | /** 36 | * RSA Maximum Encrypted Plaintext Size 37 | */ 38 | private static final int MAX_ENCRYPT_BLOCK = 117; 39 | 40 | /** 41 | * RSA Maximum decrypted ciphertext size 42 | */ 43 | private static final int MAX_DECRYPT_BLOCK = 128; 44 | 45 | /** 46 | * encryption 47 | * @param data data 48 | * @param publicKey publicKey 49 | * @return byte 50 | * @throws Exception Exception 51 | */ 52 | public static byte[] encrypt(byte[] data, String publicKey) 53 | throws Exception { 54 | byte[] keyBytes = Base64Util.decode(publicKey); 55 | X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 56 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 57 | Key publicK = keyFactory.generatePublic(x509KeySpec); 58 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 59 | cipher.init(Cipher.ENCRYPT_MODE, publicK); 60 | int inputLen = data.length; 61 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 62 | int offSet = 0; 63 | byte[] cache; 64 | int i = 0; 65 | // Sectional Encryption of Data 66 | while (inputLen - offSet > 0) { 67 | if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { 68 | cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); 69 | } else { 70 | cache = cipher.doFinal(data, offSet, inputLen - offSet); 71 | } 72 | out.write(cache, 0, cache.length); 73 | i++; 74 | offSet = i * MAX_ENCRYPT_BLOCK; 75 | } 76 | byte[] encryptedData = out.toByteArray(); 77 | out.close(); 78 | return encryptedData; 79 | } 80 | 81 | /** 82 | * Decrypt 83 | * @param text text 84 | * @param privateKey privateKey 85 | * @return byte 86 | * @throws Exception Exception 87 | */ 88 | public static byte[] decrypt(byte[] text, String privateKey) 89 | throws Exception { 90 | byte[] keyBytes = Base64Util.decode(privateKey); 91 | PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); 92 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 93 | Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); 94 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); 95 | cipher.init(Cipher.DECRYPT_MODE, privateK); 96 | int inputLen = text.length; 97 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 98 | int offSet = 0; 99 | byte[] cache; 100 | int i = 0; 101 | // Sectional Encryption of Data 102 | while (inputLen - offSet > 0) { 103 | if (inputLen - offSet > MAX_DECRYPT_BLOCK) { 104 | cache = cipher.doFinal(text, offSet, MAX_DECRYPT_BLOCK); 105 | } else { 106 | cache = cipher.doFinal(text, offSet, inputLen - offSet); 107 | } 108 | out.write(cache, 0, cache.length); 109 | i++; 110 | offSet = i * MAX_DECRYPT_BLOCK; 111 | } 112 | byte[] decryptedData = out.toByteArray(); 113 | out.close(); 114 | return decryptedData; 115 | } 116 | 117 | /** 118 | * 随机生成密钥对 119 | * @throws NoSuchAlgorithmException 找不到对应的算法 120 | * @return keyInfo 对应的密钥对 121 | */ 122 | public static KeyInfo genKeyPair() throws NoSuchAlgorithmException { 123 | // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 124 | KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); 125 | // 初始化密钥对生成器,密钥大小为96-1024位 126 | keyPairGen.initialize(1024,new SecureRandom()); 127 | // 生成一个密钥对,保存在keyPair中 128 | KeyPair keyPair = keyPairGen.generateKeyPair(); 129 | RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥 130 | RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥 131 | String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded())); 132 | // 得到私钥字符串 133 | String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded()))); 134 | // 将公钥和私钥保存到KeyInfo 135 | KeyInfo keyInfo = new KeyInfo(); 136 | keyInfo.setPrivateKey(privateKeyString); 137 | keyInfo.setPublicKey(publicKeyString); 138 | return keyInfo; 139 | } 140 | 141 | public static void main(String[] args) throws Exception { 142 | System.out.println( 143 | genKeyPair().getPrivateKey() 144 | ); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.barcke.y 8 | rsa-body-spring-boot 9 | 1.0.0 10 | Springboot 参数自动加解密 11 | 12 | rsa-body-spring-boot 13 | jar 14 | https://github.com/Barcke/rsa-body-spring-boot 15 | 16 | 17 | UTF-8 18 | UTF-8 19 | 1.8 20 | 1.8 21 | 1.8 22 | true 23 | 2.1.4.RELEASE 24 | UTF-8 25 | ${java.home}/../bin/javadoc 26 | 27 | 28 | 29 | 30 | The Apache Software License, Version 2.0 31 | http://www.apache.org/licenses/LICENSE-2.0.txt 32 | 33 | 34 | 35 | 36 | https://github.com/Barcke/rsa-body-spring-boot 37 | scm:git:git@github.com:Barcke/rsa-body-spring-boot.git 38 | scm:git:git@github.com:Barcke/rsa-body-spring-boot.git 39 | 40 | 41 | 42 | 43 | barcke 44 | barcke 45 | barcke@163.com 46 | 47 | Developer 48 | 49 | +8 50 | 51 | 52 | 53 | 54 | 55 | release 56 | 57 | true 58 | 59 | 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-source-plugin 64 | 2.2.1 65 | 66 | 67 | package 68 | 69 | jar-no-fork 70 | 71 | 72 | 73 | 74 | 75 | org.apache.maven.plugins 76 | maven-javadoc-plugin 77 | 2.9.1 78 | 79 | 80 | package 81 | 82 | jar 83 | 84 | 85 | 86 | 87 | 88 | org.apache.maven.plugins 89 | maven-gpg-plugin 90 | 1.6 91 | 92 | 93 | sign-artifacts 94 | verify 95 | 96 | sign 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | ossrh 106 | https://oss.sonatype.org/content/repositories/snapshots/ 107 | 108 | 109 | ossrh 110 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | org.springframework.boot 120 | spring-boot-starter 121 | true 122 | 123 | 124 | 125 | org.springframework.boot 126 | spring-boot-starter-web 127 | true 128 | 129 | 130 | 131 | org.springframework.boot 132 | spring-boot-starter-test 133 | test 134 | 135 | 136 | 137 | commons-codec 138 | commons-codec 139 | 140 | 141 | 142 | org.apache.commons 143 | commons-lang3 144 | 3.8.1 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | org.springframework.boot 158 | spring-boot-dependencies 159 | ${springboot-version} 160 | pom 161 | import 162 | 163 | 164 | 165 | 166 | 167 | --------------------------------------------------------------------------------